summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHolger Behrens <holger.behrens@windriver.com>2015-02-13 12:13:58 +0100
committerHolger Behrens <holger.behrens@windriver.com>2015-02-13 12:13:58 +0100
commit1faf63f8a7a557450bac238ddc1fb95593eadd08 (patch)
tree4c9909c63b44d310acdb66106d654ad18f98bd81
parentb35fcff59281e81b9fdb64448c5a9d011e0d9a28 (diff)
downloadgenivi-demo-platform-hmi-1faf63f8a7a557450bac238ddc1fb95593eadd08.tar.gz
genivi-demo-platform-hmi: uprev to version 0.3
Signed-off-by: Holger Behrens <holger.behrens@windriver.com>
-rw-r--r--configure.ac20
-rw-r--r--genivi-demo-platform-hmi.bb27
-rw-r--r--include/gdp-dbus-service.h42
-rw-r--r--include/gdp-dbus-systemd.h53
-rw-r--r--include/gdp-hmi-apps.h60
-rw-r--r--include/gdp-hmi-surfaces.h90
-rw-r--r--protocol/Makefile.am3
-rw-r--r--protocol/dbus/Makefile.am19
-rw-r--r--protocol/dbus/gdp-hmi-introspect.xml29
-rw-r--r--protocol/dbus/systemd-login1.xml272
-rw-r--r--protocol/dbus/systemd-systemd1.xml437
-rw-r--r--src/Makefile.am35
-rw-r--r--src/gdp-dbus-service.cpp83
-rw-r--r--src/gdp-dbus-systemd.cpp39
-rw-r--r--src/gdp-hmi-controller.c471
-rw-r--r--src/gdp-hmi-controller.cpp705
16 files changed, 1884 insertions, 501 deletions
diff --git a/configure.ac b/configure.ac
index a88da25..17e2faf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -13,6 +13,9 @@
# List of changes:
# 23.Jan.2015, Holger Behrens, written
# 05.Feb.2015, Holger Behrens, added support for 'doc' making
+# 06.Feb.2015, Holger Behrens, added support for C++ source
+# updated CONTROL flag
+# 09.Feb.2015, Holger Behrens, add support for dbus/dbus-c++/glib
AC_PREREQ([2.69])
AC_INIT([genivi-demo-platform-hmi], [0.2],
@@ -25,6 +28,7 @@ AM_SILENT_RULES([yes])
# Check for programs
AC_PROG_CC
+AC_PROG_CXX
# Initialize libtool
LT_PREREQ([2.4])
@@ -32,9 +36,16 @@ LT_INIT([disable-static])
PKG_PROG_PKG_CONFIG()
+PKG_CHECK_MODULES([DBUS], [
+ dbus-1
+ dbus-c++-1
+ dbus-c++-glib-1
+ ])
PKG_CHECK_MODULES([CONTROL], [
+ wayland-client >= 1.5.0
weston >= 1.5.0
- libsystemd])
+ libsystemd
+ glib-2.0])
PKG_CHECK_MODULES([PLUGIN], [weston >= 1.5.0 cairo xkbcommon])
PKG_CHECK_MODULES([CLIENT], [
wayland-client >= 1.5.0
@@ -60,6 +71,10 @@ WAYLAND_PREFIX=`$PKG_CONFIG --variable=prefix wayland-client`
AC_PATH_PROG([WAYLAND_SCANNER], [wayland-scanner],,
[${WAYLAND_PREFIX}/bin$PATH_SEPARATOR$PATH])
+# check for dbusxx-xml2cpp
+AC_PATH_PROG([XML2CPP], [dbusxx-xml2cpp])
+
+# handle arguments
AM_CONDITIONAL(BUILD_DOCS, [test x$enable_documentation = xyes])
if test "x$enable_documentation" = "xyes"; then
AC_PATH_PROG(DOXYGEN, doxygen)
@@ -75,9 +90,10 @@ AC_CONFIG_FILES([Makefile])
AC_CONFIG_FILES([doc/Makefile])
AC_CONFIG_FILES([doc/doxygen/Makefile])
AC_CONFIG_FILES([protocol/Makefile])
+AC_CONFIG_FILES([protocol/dbus/Makefile])
AC_CONFIG_FILES([src/Makefile])
AC_CONFIG_HEADERS([config.h])
-AC_CONFIG_SRCDIR(src/gdp-hmi-controller.c)
+AC_CONFIG_SRCDIR(src/gdp-hmi-controller.cpp)
# enable C standard as published in 2011 as ISO/IEC 9899:2011 (known as C11)
CFLAGS="$CFLAGS -std=c11"
diff --git a/genivi-demo-platform-hmi.bb b/genivi-demo-platform-hmi.bb
index 979e2bc..d5d05e3 100644
--- a/genivi-demo-platform-hmi.bb
+++ b/genivi-demo-platform-hmi.bb
@@ -1,12 +1,12 @@
# Copyright (C) 2015 GENIVI Alliance
# Released under the MIT license (see COPYING.MIT for the terms)
-SUMMARY = "Simple HMI for the GENIVI Demo Platform (GDP)"
+SUMMARY = "Simple HMI for the GENIVI Demo Platform (GDP)"
HOMEPAGE = "http://projects.genivi.org/genivi-demo-platform/"
-LICENSE = "MPL-2.0"
+LICENSE = "MPL-2.0"
LIC_FILES_CHKSUM = "file://LICENSE;md5=815ca599c9df247a0c7f619bab123dad"
-DEPENDS = "wayland-ivi-extension weston"
+DEPENDS = "wayland-ivi-extension weston dbus-c++ dbus-c++-native systemd"
# SRC_URI = "git://git.projects.genivi.org/genivi-demo-platform-hmi.git"
# SRCREV = ""
@@ -17,23 +17,4 @@ inherit externalsrc
EXTERNALSRC = "/home/holger/Projects/GDP/stash.wrs.com/genivi-demo-platform-hmi"
# make sure this matches the version given in configure.ac
-PV = "0.2"
-
-# by default the plugin should end up as:
-# /usr/lib/weston/genivi-demo-platform-hmi.so
-# to load this plugin you need to add this (.so) to your weston.ini ivi-module
-FILES_${PN} += "\
- ${datadir}/weston/* \
- ${libdir}/weston/genivi-demo-platform-hmi.so \
- "
-FILES_${PN}-dev += "\
- ${libdir}/weston/genivi-demo-platform-hmi.la \
- "
-FILES_${PN}-dbg += "\
- ${libdir}/weston/.debug/* \
- "
-
-do_install_append() {
- install -d ${D}${datadir}/weston
- install -m 0444 ${S}/assets/GDP_Panel.png ${D}${datadir}/weston/GDP_Panel.png
-}
+PV = "0.3"
diff --git a/include/gdp-dbus-service.h b/include/gdp-dbus-service.h
new file mode 100644
index 0000000..ccb7fe2
--- /dev/null
+++ b/include/gdp-dbus-service.h
@@ -0,0 +1,42 @@
+/**
+ * SPDX license identifier: MPL-2.0
+ *
+ * Copyright (C) 2015, GENIVI Alliance
+ *
+ * This file is part of GENIVI Demo Platform HMI.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License (MPL), 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/.
+ *
+ * For further information see http://www.genivi.org/.
+ *
+ * List of changes:
+ * 10.Feb.2014, Holger Behrens, written
+ */
+
+#ifndef GDP_HMI_SERVICE_H
+#define GDP_HMI_SERVICE_H
+
+#include <dbus-c++/dbus.h>
+#include <dbus-c++/glib-integration.h>
+#include <systemd/sd-journal.h>
+
+#include "gdp-hmi-server-glue.h"
+
+static const char *GDP_DBUS_SERVICE_NAME = "org.genivi.gdp.hmi.controller";
+static const char *GDP_DBUS_SERVICE_PATH = "/org/genivi/gdp/hmi/controller";
+
+class HmiService : public org::genivi::gdp::HMI_Controller_adaptor,
+ public DBus::IntrospectableAdaptor,
+ public DBus::ObjectAdaptor
+{
+public:
+ HmiService(DBus::Connection &connection);
+
+ int64_t GetId();
+
+ std::string Show(const std::string &name);
+};
+
+#endif // GDP_HMI_SERVICE_H \ No newline at end of file
diff --git a/include/gdp-dbus-systemd.h b/include/gdp-dbus-systemd.h
new file mode 100644
index 0000000..9ae835e
--- /dev/null
+++ b/include/gdp-dbus-systemd.h
@@ -0,0 +1,53 @@
+/**
+ * SPDX license identifier: MPL-2.0
+ *
+ * Copyright (C) 2015, GENIVI Alliance
+ *
+ * This file is part of GENIVI Demo Platform HMI.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License (MPL), 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/.
+ *
+ * For further information see http://www.genivi.org/.
+ *
+ * List of changes:
+ * 11.Feb.2014, Holger Behrens, written
+ */
+
+#ifndef GDP_SYSTEMD_SERVICE_H
+#define GDP_SYSTEMD_SERVICE_H
+
+#include <dbus-c++/dbus.h>
+#include <dbus-c++/glib-integration.h>
+#include <systemd/sd-journal.h>
+
+#include "systemd1-client-glue.h"
+
+static const char *SYSTEMD_DBUS_SERVICE_NAME = "org.freedesktop.systemd1";
+static const char *SYSTEMD_DBUS_SERVICE_PATH = "/org/freedesktop/systemd1";
+
+class SystemdService : public org::freedesktop::systemd1::Manager_proxy,
+ public DBus::IntrospectableProxy,
+ public DBus::ObjectProxy
+{
+public:
+ SystemdService(DBus::Connection &connection,
+ const char *path, const char *service);
+
+private:
+ // make virtual functions dirty no-op's
+ void UnitNew(const std::string& argin0, const ::DBus::Path& argin1){}
+ void UnitRemoved(const std::string& argin0, const ::DBus::Path& argin1) {}
+ void JobNew(const uint32_t& argin0, const ::DBus::Path& argin1,
+ const std::string& argin2) {}
+ void JobRemoved(const uint32_t& argin0, const ::DBus::Path& argin1,
+ const std::string& argin2, const std::string& argin3) {}
+ void StartupFinished(const uint64_t& argin0, const uint64_t& argin1,
+ const uint64_t& argin2, const uint64_t& argin3,
+ const uint64_t& argin4, const uint64_t& argin5) {}
+ void UnitFilesChanged() {}
+ void Reloading(const bool& argin0) {}
+};
+
+#endif // GDP_SYSTEMD_SERVICE_H \ No newline at end of file
diff --git a/include/gdp-hmi-apps.h b/include/gdp-hmi-apps.h
new file mode 100644
index 0000000..1618650
--- /dev/null
+++ b/include/gdp-hmi-apps.h
@@ -0,0 +1,60 @@
+/**
+ * SPDX license identifier: MPL-2.0
+ *
+ * Copyright (C) 2015, GENIVI Alliance
+ *
+ * This file is part of GENIVI Demo Platform HMI.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License (MPL), 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/.
+ *
+ * For further information see http://www.genivi.org/.
+ *
+ * List of changes:
+ * 11.Feb.2014, Holger Behrens, written
+ */
+
+#ifndef GDP_HMI_APP_H
+#define GDP_HMI_APP_H
+
+#define GDP_PANEL_SURFACE_ID 0
+#define GDP_PANEL_LAYER_ID 0
+#define GDP_PANEL_UNIT "gdp-hmi-panel.service"
+
+#define GDP_LAUNCHER_SURFACE_ID 1
+#define GDP_LAUNCHER_LAYER_ID 100
+#define GDP_LAUNCHER_UNIT "gdp-hmi-launcher.service"
+
+#define GDP_BACKGROUND_SURFACE_ID 2
+#define GDP_BACKGROUND_LAYER_ID 200
+#define GDP_BACKGROUND_UNIT "gdp-hmi-background.service"
+
+#define QML_EXAMPLE_SURFACE_ID 3
+#define QML_EXAMPLE_LAYER_ID 300
+#define QML_EXAMPLE_UNIT "qml-example.service"
+
+#define AM_DEMO_SURFACE_ID 20
+#define AM_DEMO_LAYER_ID 300
+#define AM_DEMO_UNIT "AudioManager_PoC.service"
+
+#define BROWSER_POC_SURFACE_ID 30
+#define BROWSER_POC_LAYER_ID 400
+#define BROWSER_POC_UNIT "browser.service"
+
+#define FSA_SURFACE_ID 40
+#define FSA_LAYER_ID 500
+#define FSA_UNIT "fsa.service"
+
+#define MOCK_NAVIGATION_SURFACE_ID 10
+#define MOCK_NAVIGATION_LAYER_ID 600
+#define MOCK_NAVIGATION_UNIT "EGLWLMockNavigation.service"
+
+#define INPUT_EVENT_EXAMPLE_SURFACE_ID 5100
+#define INPUT_EVENT_EXAMPLE_LAYER_ID 700
+#define INPUT_EVENT_EXAMPLE_UNIT "EGLWLInputEventExample.service"
+
+#define GDP_MAX_LAYER_ID 800
+#define GDP_LAYER_ID_INCR 100
+
+#endif // GDP_HMI_APP_H \ No newline at end of file
diff --git a/include/gdp-hmi-surfaces.h b/include/gdp-hmi-surfaces.h
new file mode 100644
index 0000000..11f3e50
--- /dev/null
+++ b/include/gdp-hmi-surfaces.h
@@ -0,0 +1,90 @@
+/**
+ * SPDX license identifier: MPL-2.0
+ *
+ * Copyright (C) 2015, GENIVI Alliance
+ *
+ * This file is part of GENIVI Demo Platform HMI.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License (MPL), 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/.
+ *
+ * For further information see http://www.genivi.org/.
+ *
+ * List of changes:
+ * 11.Feb.2014, Holger Behrens, written
+ */
+
+#ifndef GDP_HMI_SURFACES_H
+#define GDP_HMI_SURFACES_H
+
+#include <string>
+#include <ilm/ilm_types.h>
+
+#include "gdp-hmi-apps.h"
+
+struct gdp_surface_context {
+ t_ilm_bool created;
+ const t_ilm_uint id_surface;
+ const t_ilm_uint id_layer;
+ const std::string unit;
+};
+
+static struct gdp_surface_context gdp_surfaces[] = {
+ {
+ ILM_FALSE,
+ GDP_PANEL_SURFACE_ID,
+ GDP_PANEL_LAYER_ID,
+ GDP_PANEL_UNIT
+ },
+ {
+ ILM_FALSE,
+ GDP_LAUNCHER_SURFACE_ID,
+ GDP_LAUNCHER_LAYER_ID,
+ GDP_LAUNCHER_UNIT
+ },
+ {
+ ILM_FALSE,
+ GDP_BACKGROUND_SURFACE_ID,
+ GDP_BACKGROUND_LAYER_ID,
+ GDP_BACKGROUND_UNIT
+ },
+ {
+ ILM_FALSE,
+ QML_EXAMPLE_SURFACE_ID,
+ QML_EXAMPLE_LAYER_ID,
+ QML_EXAMPLE_UNIT
+ },
+ {
+ ILM_FALSE,
+ AM_DEMO_SURFACE_ID,
+ AM_DEMO_LAYER_ID,
+ AM_DEMO_UNIT
+ },
+ {
+ ILM_FALSE,
+ BROWSER_POC_SURFACE_ID,
+ BROWSER_POC_LAYER_ID,
+ BROWSER_POC_UNIT
+ },
+ {
+ ILM_FALSE,
+ FSA_SURFACE_ID,
+ FSA_LAYER_ID,
+ FSA_UNIT
+ },
+ {
+ ILM_FALSE,
+ MOCK_NAVIGATION_SURFACE_ID,
+ MOCK_NAVIGATION_LAYER_ID,
+ MOCK_NAVIGATION_UNIT
+ },
+ {
+ ILM_FALSE,
+ INPUT_EVENT_EXAMPLE_SURFACE_ID,
+ INPUT_EVENT_EXAMPLE_LAYER_ID,
+ INPUT_EVENT_EXAMPLE_UNIT
+ },
+};
+
+#endif // GDP_HMI_SURFACES_H \ No newline at end of file
diff --git a/protocol/Makefile.am b/protocol/Makefile.am
index c0ee80d..a444b80 100644
--- a/protocol/Makefile.am
+++ b/protocol/Makefile.am
@@ -12,6 +12,9 @@
#
# List of changes:
# 23.Jan.2015, Holger Behrens, written
+# 10.Feb.2015, Holger Behrens, defined SUBDIRS
+
+SUBDIRS = dbus
EXTRA_DIST = \
ivi-application.xml \
diff --git a/protocol/dbus/Makefile.am b/protocol/dbus/Makefile.am
new file mode 100644
index 0000000..bdc8c06
--- /dev/null
+++ b/protocol/dbus/Makefile.am
@@ -0,0 +1,19 @@
+# SPDX license identifier: MPL-2.0
+#
+# Copyright (C) 2015, GENIVI Alliance
+#
+# This file is part of the GENIVI Demo Platform HMI.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License (MPL), 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/.
+#
+# For further information see http://www.genivi.org/.
+#
+# List of changes:
+# 10.Feb.2015, Holger Behrens, written
+
+EXTRA_DIST = \
+ gdp-hmi-introspect.xml \
+ systemd-systemd1.xml \
+ systemd-login1.xml
diff --git a/protocol/dbus/gdp-hmi-introspect.xml b/protocol/dbus/gdp-hmi-introspect.xml
new file mode 100644
index 0000000..3bb57c1
--- /dev/null
+++ b/protocol/dbus/gdp-hmi-introspect.xml
@@ -0,0 +1,29 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+ "http://standards.freedesktop.org/dbus/1.0/introspect.dtd">
+<!--
+ * SPDX license identifier: MPL-2.0
+ *
+ * Copyright (C) 2015, GENIVI Alliance
+ *
+ * This file is part of GENIVI Demo Platform HMI.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License (MPL), 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/.
+ *
+ * For further information see http://www.genivi.org/.
+ *
+ * List of changes:
+ * 10.Feb.2014, Holger Behrens, written
+-->
+<node name="/org/genivi/gdp/hmi/controller">
+ <interface name="org.genivi.gdp.HMI_Controller">
+ <method name="GetId">
+ <arg type="x" name="pid" direction="out"/>
+ </method>
+ <method name="Show">
+ <arg type="s" name="unit" direction="in"/>
+ <arg type="s" name="status" direction="out"/>
+ </method>
+ </interface>
+</node>
diff --git a/protocol/dbus/systemd-login1.xml b/protocol/dbus/systemd-login1.xml
new file mode 100644
index 0000000..49dfcce
--- /dev/null
+++ b/protocol/dbus/systemd-login1.xml
@@ -0,0 +1,272 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+ <interface name="org.freedesktop.DBus.Peer">
+ <method name="Ping"/>
+ <method name="GetMachineId">
+ <arg type="s" name="machine_uuid" direction="out"/>
+ </method>
+ </interface>
+ <interface name="org.freedesktop.DBus.Introspectable">
+ <method name="Introspect">
+ <arg name="data" type="s" direction="out"/>
+ </method>
+ </interface>
+ <interface name="org.freedesktop.DBus.Properties">
+ <method name="Get">
+ <arg name="interface" direction="in" type="s"/>
+ <arg name="property" direction="in" type="s"/>
+ <arg name="value" direction="out" type="v"/>
+ </method>
+ <method name="GetAll">
+ <arg name="interface" direction="in" type="s"/>
+ <arg name="properties" direction="out" type="a{sv}"/>
+ </method>
+ <method name="Set">
+ <arg name="interface" direction="in" type="s"/>
+ <arg name="property" direction="in" type="s"/>
+ <arg name="value" direction="in" type="v"/>
+ </method>
+ <signal name="PropertiesChanged">
+ <arg type="s" name="interface"/>
+ <arg type="a{sv}" name="changed_properties"/>
+ <arg type="as" name="invalidated_properties"/>
+ </signal>
+ </interface>
+ <interface name="org.freedesktop.login1.Manager">
+ <property name="NAutoVTs" type="u" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="KillOnlyUsers" type="as" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="KillExcludeUsers" type="as" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="KillUserProcesses" type="b" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="IdleHint" type="b" access="read">
+ </property>
+ <property name="IdleSinceHint" type="t" access="read">
+ </property>
+ <property name="IdleSinceHintMonotonic" type="t" access="read">
+ </property>
+ <property name="BlockInhibited" type="s" access="read">
+ </property>
+ <property name="DelayInhibited" type="s" access="read">
+ </property>
+ <property name="InhibitDelayMaxUSec" type="t" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="HandlePowerKey" type="s" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="HandleSuspendKey" type="s" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="HandleHibernateKey" type="s" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="HandleLidSwitch" type="s" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="IdleAction" type="s" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="IdleActionUSec" type="t" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="PreparingForShutdown" type="b" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
+ </property>
+ <property name="PreparingForSleep" type="b" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
+ </property>
+ <method name="GetSession">
+ <arg type="s" direction="in"/>
+ <arg type="o" direction="out"/>
+ </method>
+ <method name="GetSessionByPID">
+ <arg type="u" direction="in"/>
+ <arg type="o" direction="out"/>
+ </method>
+ <method name="GetUser">
+ <arg type="u" direction="in"/>
+ <arg type="o" direction="out"/>
+ </method>
+ <method name="GetUserByPID">
+ <arg type="u" direction="in"/>
+ <arg type="o" direction="out"/>
+ </method>
+ <method name="GetSeat">
+ <arg type="s" direction="in"/>
+ <arg type="o" direction="out"/>
+ </method>
+ <method name="ListSessions">
+ <arg type="a(susso)" direction="out"/>
+ </method>
+ <method name="ListUsers">
+ <arg type="a(uso)" direction="out"/>
+ </method>
+ <method name="ListSeats">
+ <arg type="a(so)" direction="out"/>
+ </method>
+ <method name="ListInhibitors">
+ <arg type="a(ssssuu)" direction="out"/>
+ </method>
+ <method name="CreateSession">
+ <arg type="u" direction="in"/>
+ <arg type="u" direction="in"/>
+ <arg type="s" direction="in"/>
+ <arg type="s" direction="in"/>
+ <arg type="s" direction="in"/>
+ <arg type="s" direction="in"/>
+ <arg type="s" direction="in"/>
+ <arg type="u" direction="in"/>
+ <arg type="s" direction="in"/>
+ <arg type="s" direction="in"/>
+ <arg type="b" direction="in"/>
+ <arg type="s" direction="in"/>
+ <arg type="s" direction="in"/>
+ <arg type="a(sv)" direction="in"/>
+ <arg type="s" direction="out"/>
+ <arg type="o" direction="out"/>
+ <arg type="s" direction="out"/>
+ <arg type="h" direction="out"/>
+ <arg type="u" direction="out"/>
+ <arg type="s" direction="out"/>
+ <arg type="u" direction="out"/>
+ <arg type="b" direction="out"/>
+ <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
+ </method>
+ <method name="ReleaseSession">
+ <arg type="s" direction="in"/>
+ <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
+ </method>
+ <method name="ActivateSession">
+ <arg type="s" direction="in"/>
+ </method>
+ <method name="ActivateSessionOnSeat">
+ <arg type="s" direction="in"/>
+ <arg type="s" direction="in"/>
+ </method>
+ <method name="LockSession">
+ <arg type="s" direction="in"/>
+ <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
+ </method>
+ <method name="UnlockSession">
+ <arg type="s" direction="in"/>
+ <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
+ </method>
+ <method name="LockSessions">
+ <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
+ </method>
+ <method name="UnlockSessions">
+ <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
+ </method>
+ <method name="KillSession">
+ <arg type="s" direction="in"/>
+ <arg type="s" direction="in"/>
+ <arg type="i" direction="in"/>
+ <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
+ </method>
+ <method name="KillUser">
+ <arg type="u" direction="in"/>
+ <arg type="i" direction="in"/>
+ <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
+ </method>
+ <method name="TerminateSession">
+ <arg type="s" direction="in"/>
+ <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
+ </method>
+ <method name="TerminateUser">
+ <arg type="u" direction="in"/>
+ <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
+ </method>
+ <method name="TerminateSeat">
+ <arg type="s" direction="in"/>
+ <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
+ </method>
+ <method name="SetUserLinger">
+ <arg type="u" direction="in"/>
+ <arg type="b" direction="in"/>
+ <arg type="b" direction="in"/>
+ </method>
+ <method name="AttachDevice">
+ <arg type="s" direction="in"/>
+ <arg type="s" direction="in"/>
+ <arg type="b" direction="in"/>
+ </method>
+ <method name="FlushDevices">
+ <arg type="b" direction="in"/>
+ </method>
+ <method name="PowerOff">
+ <arg type="b" direction="in"/>
+ </method>
+ <method name="Reboot">
+ <arg type="b" direction="in"/>
+ </method>
+ <method name="Suspend">
+ <arg type="b" direction="in"/>
+ </method>
+ <method name="Hibernate">
+ <arg type="b" direction="in"/>
+ </method>
+ <method name="HybridSleep">
+ <arg type="b" direction="in"/>
+ </method>
+ <method name="CanPowerOff">
+ <arg type="s" direction="out"/>
+ </method>
+ <method name="CanReboot">
+ <arg type="s" direction="out"/>
+ </method>
+ <method name="CanSuspend">
+ <arg type="s" direction="out"/>
+ </method>
+ <method name="CanHibernate">
+ <arg type="s" direction="out"/>
+ </method>
+ <method name="CanHybridSleep">
+ <arg type="s" direction="out"/>
+ </method>
+ <method name="Inhibit">
+ <arg type="s" direction="in"/>
+ <arg type="s" direction="in"/>
+ <arg type="s" direction="in"/>
+ <arg type="s" direction="in"/>
+ <arg type="h" direction="out"/>
+ </method>
+ <signal name="SessionNew">
+ <arg type="s"/>
+ <arg type="o"/>
+ </signal>
+ <signal name="SessionRemoved">
+ <arg type="s"/>
+ <arg type="o"/>
+ </signal>
+ <signal name="UserNew">
+ <arg type="u"/>
+ <arg type="o"/>
+ </signal>
+ <signal name="UserRemoved">
+ <arg type="u"/>
+ <arg type="o"/>
+ </signal>
+ <signal name="SeatNew">
+ <arg type="s"/>
+ <arg type="o"/>
+ </signal>
+ <signal name="SeatRemoved">
+ <arg type="s"/>
+ <arg type="o"/>
+ </signal>
+ <signal name="PrepareForShutdown">
+ <arg type="b"/>
+ </signal>
+ <signal name="PrepareForSleep">
+ <arg type="b"/>
+ </signal>
+ </interface>
+</node>
diff --git a/protocol/dbus/systemd-systemd1.xml b/protocol/dbus/systemd-systemd1.xml
new file mode 100644
index 0000000..3cdc990
--- /dev/null
+++ b/protocol/dbus/systemd-systemd1.xml
@@ -0,0 +1,437 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+ <interface name="org.freedesktop.DBus.Peer">
+ <method name="Ping"/>
+ <method name="GetMachineId">
+ <arg type="s" name="machine_uuid" direction="out"/>
+ </method>
+ </interface>
+ <interface name="org.freedesktop.DBus.Introspectable">
+ <method name="Introspect">
+ <arg name="data" type="s" direction="out"/>
+ </method>
+ </interface>
+ <interface name="org.freedesktop.DBus.Properties">
+ <method name="Get">
+ <arg name="interface" direction="in" type="s"/>
+ <arg name="property" direction="in" type="s"/>
+ <arg name="value" direction="out" type="v"/>
+ </method>
+ <method name="GetAll">
+ <arg name="interface" direction="in" type="s"/>
+ <arg name="properties" direction="out" type="a{sv}"/>
+ </method>
+ <method name="Set">
+ <arg name="interface" direction="in" type="s"/>
+ <arg name="property" direction="in" type="s"/>
+ <arg name="value" direction="in" type="v"/>
+ </method>
+ <signal name="PropertiesChanged">
+ <arg type="s" name="interface"/>
+ <arg type="a{sv}" name="changed_properties"/>
+ <arg type="as" name="invalidated_properties"/>
+ </signal>
+ </interface>
+ <interface name="org.freedesktop.systemd1.Manager">
+ <property name="Version" type="s" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="Features" type="s" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="Virtualization" type="s" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="Architecture" type="s" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="Tainted" type="s" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="FirmwareTimestamp" type="t" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="FirmwareTimestampMonotonic" type="t" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="LoaderTimestamp" type="t" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="LoaderTimestampMonotonic" type="t" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="KernelTimestamp" type="t" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="KernelTimestampMonotonic" type="t" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="InitRDTimestamp" type="t" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="InitRDTimestampMonotonic" type="t" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="UserspaceTimestamp" type="t" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="UserspaceTimestampMonotonic" type="t" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="FinishTimestamp" type="t" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="FinishTimestampMonotonic" type="t" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="SecurityStartTimestamp" type="t" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="SecurityStartTimestampMonotonic" type="t" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="SecurityFinishTimestamp" type="t" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="SecurityFinishTimestampMonotonic" type="t" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="GeneratorsStartTimestamp" type="t" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="GeneratorsStartTimestampMonotonic" type="t" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="GeneratorsFinishTimestamp" type="t" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="GeneratorsFinishTimestampMonotonic" type="t" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="UnitsLoadStartTimestamp" type="t" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="UnitsLoadStartTimestampMonotonic" type="t" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="UnitsLoadFinishTimestamp" type="t" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="UnitsLoadFinishTimestampMonotonic" type="t" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="LogLevel" type="s" access="readwrite">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
+ <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
+ </property>
+ <property name="LogTarget" type="s" access="readwrite">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
+ <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
+ </property>
+ <property name="NNames" type="u" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
+ </property>
+ <property name="NFailedUnits" type="u" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
+ </property>
+ <property name="NJobs" type="u" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
+ </property>
+ <property name="NInstalledJobs" type="u" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
+ </property>
+ <property name="NFailedJobs" type="u" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
+ </property>
+ <property name="Progress" type="d" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
+ </property>
+ <property name="Environment" type="as" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
+ </property>
+ <property name="ConfirmSpawn" type="b" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="ShowStatus" type="b" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="UnitPath" type="as" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="DefaultStandardOutput" type="s" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="DefaultStandardError" type="s" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ </property>
+ <property name="RuntimeWatchdogUSec" type="t" access="readwrite">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
+ </property>
+ <property name="ShutdownWatchdogUSec" type="t" access="readwrite">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+ <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
+ </property>
+ <property name="ControlGroup" type="s" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
+ </property>
+ <property name="SystemState" type="s" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
+ </property>
+ <method name="GetUnit">
+ <arg type="s" direction="in"/>
+ <arg type="o" direction="out"/>
+ </method>
+ <method name="GetUnitByPID">
+ <arg type="u" direction="in"/>
+ <arg type="o" direction="out"/>
+ </method>
+ <method name="LoadUnit">
+ <arg type="s" direction="in"/>
+ <arg type="o" direction="out"/>
+ </method>
+ <method name="StartUnit">
+ <arg type="s" direction="in"/>
+ <arg type="s" direction="in"/>
+ <arg type="o" direction="out"/>
+ </method>
+ <method name="StartUnitReplace">
+ <arg type="s" direction="in"/>
+ <arg type="s" direction="in"/>
+ <arg type="s" direction="in"/>
+ <arg type="o" direction="out"/>
+ </method>
+ <method name="StopUnit">
+ <arg type="s" direction="in"/>
+ <arg type="s" direction="in"/>
+ <arg type="o" direction="out"/>
+ </method>
+ <method name="ReloadUnit">
+ <arg type="s" direction="in"/>
+ <arg type="s" direction="in"/>
+ <arg type="o" direction="out"/>
+ </method>
+ <method name="RestartUnit">
+ <arg type="s" direction="in"/>
+ <arg type="s" direction="in"/>
+ <arg type="o" direction="out"/>
+ </method>
+ <method name="TryRestartUnit">
+ <arg type="s" direction="in"/>
+ <arg type="s" direction="in"/>
+ <arg type="o" direction="out"/>
+ </method>
+ <method name="ReloadOrRestartUnit">
+ <arg type="s" direction="in"/>
+ <arg type="s" direction="in"/>
+ <arg type="o" direction="out"/>
+ </method>
+ <method name="ReloadOrTryRestartUnit">
+ <arg type="s" direction="in"/>
+ <arg type="s" direction="in"/>
+ <arg type="o" direction="out"/>
+ </method>
+ <method name="KillUnit">
+ <arg type="s" direction="in"/>
+ <arg type="s" direction="in"/>
+ <arg type="i" direction="in"/>
+ </method>
+ <method name="ResetFailedUnit">
+ <arg type="s" direction="in"/>
+ </method>
+ <method name="SetUnitProperties">
+ <arg type="s" direction="in"/>
+ <arg type="b" direction="in"/>
+ <arg type="a(sv)" direction="in"/>
+ </method>
+ <method name="StartTransientUnit">
+ <arg type="s" direction="in"/>
+ <arg type="s" direction="in"/>
+ <arg type="a(sv)" direction="in"/>
+ <arg type="a(sa(sv))" direction="in"/>
+ <arg type="o" direction="out"/>
+ </method>
+ <method name="GetJob">
+ <arg type="u" direction="in"/>
+ <arg type="o" direction="out"/>
+ </method>
+ <method name="CancelJob">
+ <arg type="u" direction="in"/>
+ </method>
+ <method name="ClearJobs">
+ <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
+ </method>
+ <method name="ResetFailed">
+ <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
+ </method>
+ <method name="ListUnits">
+ <arg type="a(ssssssouso)" direction="out"/>
+ </method>
+ <method name="ListUnitsFiltered">
+ <arg type="as" direction="in"/>
+ <arg type="a(ssssssouso)" direction="out"/>
+ </method>
+ <method name="ListJobs">
+ <arg type="a(usssoo)" direction="out"/>
+ </method>
+ <method name="Subscribe">
+ </method>
+ <method name="Unsubscribe">
+ </method>
+ <method name="Dump">
+ <arg type="s" direction="out"/>
+ </method>
+ <method name="CreateSnapshot">
+ <arg type="s" direction="in"/>
+ <arg type="b" direction="in"/>
+ <arg type="o" direction="out"/>
+ <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
+ </method>
+ <method name="RemoveSnapshot">
+ <arg type="s" direction="in"/>
+ <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
+ </method>
+ <method name="Reload">
+ </method>
+ <method name="Reexecute">
+ </method>
+ <method name="Exit">
+ <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
+ </method>
+ <method name="Reboot">
+ <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
+ </method>
+ <method name="PowerOff">
+ <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
+ </method>
+ <method name="Halt">
+ <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
+ </method>
+ <method name="KExec">
+ <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
+ </method>
+ <method name="SwitchRoot">
+ <arg type="s" direction="in"/>
+ <arg type="s" direction="in"/>
+ <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
+ </method>
+ <method name="SetEnvironment">
+ <arg type="as" direction="in"/>
+ <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
+ </method>
+ <method name="UnsetEnvironment">
+ <arg type="as" direction="in"/>
+ <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
+ </method>
+ <method name="UnsetAndSetEnvironment">
+ <arg type="as" direction="in"/>
+ <arg type="as" direction="in"/>
+ <annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
+ </method>
+ <method name="ListUnitFiles">
+ <arg type="a(ss)" direction="out"/>
+ </method>
+ <method name="GetUnitFileState">
+ <arg type="s" direction="in"/>
+ <arg type="s" direction="out"/>
+ </method>
+ <method name="EnableUnitFiles">
+ <arg type="as" direction="in"/>
+ <arg type="b" direction="in"/>
+ <arg type="b" direction="in"/>
+ <arg type="b" direction="out"/>
+ <arg type="a(sss)" direction="out"/>
+ </method>
+ <method name="DisableUnitFiles">
+ <arg type="as" direction="in"/>
+ <arg type="b" direction="in"/>
+ <arg type="a(sss)" direction="out"/>
+ </method>
+ <method name="ReenableUnitFiles">
+ <arg type="as" direction="in"/>
+ <arg type="b" direction="in"/>
+ <arg type="b" direction="in"/>
+ <arg type="b" direction="out"/>
+ <arg type="a(sss)" direction="out"/>
+ </method>
+ <method name="LinkUnitFiles">
+ <arg type="as" direction="in"/>
+ <arg type="b" direction="in"/>
+ <arg type="b" direction="in"/>
+ <arg type="a(sss)" direction="out"/>
+ </method>
+ <method name="PresetUnitFiles">
+ <arg type="as" direction="in"/>
+ <arg type="b" direction="in"/>
+ <arg type="b" direction="in"/>
+ <arg type="b" direction="out"/>
+ <arg type="a(sss)" direction="out"/>
+ </method>
+ <method name="PresetUnitFilesWithMode">
+ <arg type="as" direction="in"/>
+ <arg type="s" direction="in"/>
+ <arg type="b" direction="in"/>
+ <arg type="b" direction="in"/>
+ <arg type="b" direction="out"/>
+ <arg type="a(sss)" direction="out"/>
+ </method>
+ <method name="MaskUnitFiles">
+ <arg type="as" direction="in"/>
+ <arg type="b" direction="in"/>
+ <arg type="b" direction="in"/>
+ <arg type="a(sss)" direction="out"/>
+ </method>
+ <method name="UnmaskUnitFiles">
+ <arg type="as" direction="in"/>
+ <arg type="b" direction="in"/>
+ <arg type="a(sss)" direction="out"/>
+ </method>
+ <method name="SetDefaultTarget">
+ <arg type="s" direction="in"/>
+ <arg type="b" direction="in"/>
+ <arg type="a(sss)" direction="out"/>
+ </method>
+ <method name="GetDefaultTarget">
+ <arg type="s" direction="out"/>
+ </method>
+ <method name="PresetAllUnitFiles">
+ <arg type="s" direction="in"/>
+ <arg type="b" direction="in"/>
+ <arg type="b" direction="in"/>
+ <arg type="a(sss)" direction="out"/>
+ </method>
+ <signal name="UnitNew">
+ <arg type="s"/>
+ <arg type="o"/>
+ </signal>
+ <signal name="UnitRemoved">
+ <arg type="s"/>
+ <arg type="o"/>
+ </signal>
+ <signal name="JobNew">
+ <arg type="u"/>
+ <arg type="o"/>
+ <arg type="s"/>
+ </signal>
+ <signal name="JobRemoved">
+ <arg type="u"/>
+ <arg type="o"/>
+ <arg type="s"/>
+ <arg type="s"/>
+ </signal>
+ <signal name="StartupFinished">
+ <arg type="t"/>
+ <arg type="t"/>
+ <arg type="t"/>
+ <arg type="t"/>
+ <arg type="t"/>
+ <arg type="t"/>
+ </signal>
+ <signal name="UnitFilesChanged">
+ </signal>
+ <signal name="Reloading">
+ <arg type="b"/>
+ </signal>
+ </interface>
+</node>
diff --git a/src/Makefile.am b/src/Makefile.am
index 1085479..ac95fb4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -12,15 +12,28 @@
#
# List of changes:
# 23.Jan.2015, Holger Behrens, written
+# 06.Feb.2015, Holger Behrens, define include directory location
+# 09.Feb.2015, Holger Behrens, add support for dbus/dbus-c++/glib
+# 10.Feb.2015, Hogler Behrens, add support for systemd1/login1 dbus-c++ client
+#
-BUILT_SOURCES = ivi-controller-client-protocol.h
+AM_CPPFLAGS = -I$(top_srcdir)/include
+BUILT_SOURCES = ivi-controller-client-protocol.h \
+ gdp-hmi-server-glue.h \
+ gdp-hmi-client-glue.h \
+ systemd1-client-glue.h \
+ login1-client-glue.h
bin_PROGRAMS = gdp-hmi-controller
-gdp_hmi_controller_CPPFLAGS = $(CONTROL_FLAGS) $(AM_CPPFLAGS)
-gdp_hmi_controller_LDADD = $(ILM_LIBS) $(CONTROL_LIBS)
+gdp_hmi_controller_CPPFLAGS = $(CONTROL_CFLAGS) $(DBUS_CFLAGS) $(AM_CPPFLAGS)
+gdp_hmi_controller_LDADD = $(ILM_LIBS) $(CONTROL_LIBS) $(DBUS_LIBS)
gdp_hmi_controller_SOURCES = \
- ivi-controller-client-protocol.h \
- gdp-hmi-controller.c
+ gdp-dbus-systemd.cpp \
+ systemd1-client-glue.h \
+ gdp-dbus-service.cpp \
+ gdp-hmi-server-glue.h \
+ ivi-controller-client-protocol.h \
+ gdp-hmi-controller.cpp
%-protocol.c : ../protocol/%.xml
$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
@@ -30,3 +43,15 @@ gdp_hmi_controller_SOURCES = \
%-client-protocol.h : ../protocol/%.xml
$(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@
+
+gdp-hmi-client-glue.h: $(top_srcdir)/protocol/dbus/gdp-hmi-introspect.xml
+ $(XML2CPP) $< --proxy=$@
+
+gdp-hmi-server-glue.h: $(top_srcdir)/protocol/dbus/gdp-hmi-introspect.xml
+ $(XML2CPP) $< --adaptor=$@
+
+systemd1-client-glue.h: $(top_srcdir)/protocol/dbus/systemd-systemd1.xml
+ $(XML2CPP) $< --proxy=$@
+
+login1-client-glue.h: $(top_srcdir)/protocol/dbus/systemd-login1.xml
+ $(XML2CPP) $< --proxy=$@
diff --git a/src/gdp-dbus-service.cpp b/src/gdp-dbus-service.cpp
new file mode 100644
index 0000000..89222ba
--- /dev/null
+++ b/src/gdp-dbus-service.cpp
@@ -0,0 +1,83 @@
+/**
+ * SPDX license identifier: MPL-2.0
+ *
+ * Copyright (C) 2015, GENIVI Alliance
+ *
+ * This file is part of GENIVI Demo Platform HMI.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License (MPL), 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/.
+ *
+ * For further information see http://www.genivi.org/.
+ *
+ * List of changes:
+ * 10.Feb.2014, Holger Behrens, written
+ */
+
+/*! \file gdp-dbus-service.cpp
+ * \brief HMI controller service API on D-Bus for the GENIVI Demo Platform
+ *
+ * This component implements the HMI controller service API and makes it
+ * available on the D-Bus session bus.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <systemd/sd-journal.h>
+
+#include "gdp-hmi-surfaces.h"
+#include "gdp-dbus-service.h"
+#include "gdp-dbus-systemd.h"
+
+extern SystemdService *gSystemdSession; // systemd on session bus (d-bus)
+extern SystemdService *gSystemd; // systemd on system bus (d-bus)
+
+HmiService::HmiService(DBus::Connection &connection)
+ : DBus::ObjectAdaptor(connection, GDP_DBUS_SERVICE_PATH)
+{
+ sd_journal_print(LOG_INFO, "HmiService - constructor (path= %s)\n",
+ GDP_DBUS_SERVICE_PATH);
+}
+
+int64_t HmiService::GetId()
+{
+ sd_journal_print(LOG_DEBUG, "HmiService::GetId() - %d\n", getpid());
+ return getpid();
+}
+
+std::string HmiService::Show(const std::string &unit)
+{
+ if (0 == unit.compare(0, 15, "poweroff.target")) {
+ sd_journal_print(LOG_DEBUG, "HmiService::Show() - %s (match)\n",
+ unit.c_str());
+ std::string path = gSystemd->StartUnit(unit, "replace");
+ } else {
+ sd_journal_print(LOG_DEBUG, "HmiService::Show() - %s\n",
+ unit.c_str());
+ for (int count = 0;
+ count < sizeof gdp_surfaces / sizeof gdp_surfaces[0]; count++) {
+ if (0 == unit.compare(gdp_surfaces[count].unit)) {
+ if (ILM_TRUE == gdp_surfaces[count].created) {
+ // FIXME
+ // bring gdp_surfaces[count].id_surface to front
+ sd_journal_print(LOG_DEBUG,
+ "HmiService::Show() - %s surface (%d) exists.\n",
+ unit.c_str(), gdp_surfaces[count].id_surface);
+ } else {
+ // request systemd to start the unit
+ std::string path = gSystemdSession->StartUnit(unit, "replace");
+ sd_journal_print(LOG_DEBUG,
+ "systemd(session)::StartUnit() - %s\n", path.c_str());
+ }
+ break; // for-loop
+ }
+ else {
+ sd_journal_print(LOG_DEBUG, "DEBUG: compare \"%s\" with \"%s\"",
+ unit.c_str(), gdp_surfaces[count].unit.c_str());
+ }
+ } // for-loop
+ }
+ return "Show unit \"" + unit + "\"!";
+}
diff --git a/src/gdp-dbus-systemd.cpp b/src/gdp-dbus-systemd.cpp
new file mode 100644
index 0000000..2f971c7
--- /dev/null
+++ b/src/gdp-dbus-systemd.cpp
@@ -0,0 +1,39 @@
+/**
+ * SPDX license identifier: MPL-2.0
+ *
+ * Copyright (C) 2015, GENIVI Alliance
+ *
+ * This file is part of GENIVI Demo Platform HMI.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License (MPL), 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/.
+ *
+ * For further information see http://www.genivi.org/.
+ *
+ * List of changes:
+ * 11.Feb.2014, Holger Behrens, written
+ */
+
+/*! \file gdp-dbus-systemd.cpp
+ * \brief HMI controller interface with systemd via D-Bus
+ *
+ * This component implements the HMI controller interface with systemd via
+ * D-Bus. Using the session bus to query application status and using the
+ * system bus for calling the systemd 'PowerOff' method.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <systemd/sd-journal.h>
+
+#include "gdp-dbus-systemd.h"
+
+SystemdService::SystemdService(DBus::Connection &connection,
+ const char *path, const char *service)
+ : DBus::ObjectProxy(connection, path, service)
+{
+ sd_journal_print(LOG_INFO, "SystemdService - constructor (path= %s)\n",
+ path);
+}
diff --git a/src/gdp-hmi-controller.c b/src/gdp-hmi-controller.c
deleted file mode 100644
index 6c4e579..0000000
--- a/src/gdp-hmi-controller.c
+++ /dev/null
@@ -1,471 +0,0 @@
-/* SPDXLicenseID: MPL-2.0
- *
- * Copyright (C) 2015, GENIVI Alliance
- *
- * This file is part of the GENIVI Demo Platform HMI.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License (MPL), 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/.
- *
- * For further information see http://www.genivi.org/.
- *
- * List of changes:
- * 23.Jan.2015, Holger Behrens, written
- * 05.Feb.2015, Holger Behrens, added surface ID '3' handling
- */
-
-/*! \file gdp-hmi-controller.c
- * \brief HMI controller for the GENIVI Demo Platform
- *
- * This component implements the HMI controller of the GENIVI Demo Platform
- * using the GENIVI Alliance wayland-ivi-extension.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <signal.h>
-#include <unistd.h>
-#include <getopt.h>
-#include <systemd/sd-journal.h>
-
-#include <ilm/ilm_types.h>
-#include <ilm/ilm_client.h>
-#include <ilm/ilm_control.h>
-
-#include "wayland-util.h"
-#include "ivi-controller-client-protocol.h"
-
-
-// definitions
-
-#define DEFAULT_SCREEN_WIDTH 1024
-#define DEFAULT_SCREEN_HEIGHT 768
-
-struct gdp_surface_context {
- t_ilm_bool created;
- t_ilm_uint id_surface;
- t_ilm_uint id_layer;
-};
-
-// initialize global variables
-
-static int verbose = 0;
-static int gRunLoop = 0;
-static t_ilm_uint screenID = 0;
-static t_ilm_uint screenWidth = DEFAULT_SCREEN_WIDTH;
-static t_ilm_uint screenHeight = DEFAULT_SCREEN_HEIGHT;
-static int surfacesArrayCount = 0;
-static unsigned int* surfacesArray = NULL;
-
-static struct gdp_surface_context gdp_surfaces[] = {
- {ILM_FALSE, 1 /* Background / Logo */, 100},
- {ILM_FALSE, 2 /* GDP HMI */, 200},
- {ILM_FALSE, 3 /* QML Example */, 300},
- {ILM_FALSE, 20 /* AudioManager PoC */, 300},
- {ILM_FALSE, 30 /* Browser PoC */, 400},
- {ILM_FALSE, 40 /* FSA PoC */, 500},
- {ILM_FALSE, 10 /* EGL Mock Navigation */, 600},
- {ILM_FALSE, 5100 /* EGL Input Example */, 700},
-};
-
-/**
- * \brief signal handler
- *
- * This function shall handle all signals of type 'SIGINT'.
- *
- */
-static void sig_handler(int signo)
-{
- signo = signo;
- printf(" signal caught\n");
- gRunLoop = 0;
-}
-
-/**
- * \brief creates IVI layer
- *
- * This function creates the following layers with the the given ID:
- *
- * Layer Assignment | Layer ID
- * -----------------: | :------:
- * background w/ logo | 100
- * launcher | 200
- * AM PoC | 300
- * Browser PoC | 400
- * FSA PoC | 500
- * MockNavigation | 600
- * InputEventExample | 700
- *
- */
-static void layer_create(void)
-{
- ilmErrorTypes callResult = ILM_FAILED;
- struct ilmScreenProperties screenProperties;
- t_ilm_layer layerid = 0;
- t_ilm_uint* pIDs = NULL;
- t_ilm_uint numberOfIDs = 0;
-
- if (!ilm_isInitialized())
- return;
-
- callResult = ilm_getScreenIDs(&numberOfIDs, &pIDs);
- if (ILM_SUCCESS != callResult) {
- sd_journal_print(LOG_ERR,
- "Error: layer_create() ilm_getScreenIDs - %s. Exiting.\n",
- ILM_ERROR_STRING(callResult));
- exit(EXIT_FAILURE);
- } else {
- screenID = pIDs[0];
- sd_journal_print(LOG_DEBUG,
- "Debug: ilm_getScreenIDs - %s. number of screens = %u\n",
- ILM_ERROR_STRING(callResult), numberOfIDs);
- }
- sd_journal_print(LOG_INFO,
- "Info: layer_create - in screen with ID = %u\n",
- screenID);
-
-
- callResult = ilm_getPropertiesOfScreen(screenID, &screenProperties);
- if (ILM_SUCCESS != callResult) {
- sd_journal_print(LOG_ERR,
- "Error: layer_create() ilm_getPropertiesOfScreen - %s. Exiting.\n",
- ILM_ERROR_STRING(callResult));
- exit(EXIT_FAILURE);
- }
- screenWidth = screenProperties.screenWidth;
- screenHeight = screenProperties.screenHeight;
- sd_journal_print(LOG_INFO,
- "Info: layer_create - screen size = %u x %u\n",
- screenWidth, screenHeight);
- if (0 == screenWidth)
- screenWidth = DEFAULT_SCREEN_WIDTH;
- if (0 == screenHeight)
- screenHeight = DEFAULT_SCREEN_HEIGHT;
-
- for(layerid = 100; layerid < 800; layerid += 100) {
- callResult = ilm_layerCreateWithDimension(&layerid,
- screenWidth, screenHeight);
- if (ILM_SUCCESS != callResult) {
- sd_journal_print(LOG_ERR,
- "Error: layer_create (id = %u) - %s\n",
- layerid, ILM_ERROR_STRING(callResult));
- break;
- } else {
- sd_journal_print(LOG_DEBUG,
- "Debug: layer_create (id = %u) - %s (%u x %u)\n",
- layerid, ILM_ERROR_STRING(callResult),
- screenWidth, screenHeight);
- }
- } // for-loop
-
- callResult = ilm_commitChanges();
- if (ILM_SUCCESS != callResult) {
- sd_journal_print(LOG_ERR,
- "Error: layer_create() ilm_commitChanges - %s. Exiting.\n",
- ILM_ERROR_STRING(callResult));
- exit(EXIT_FAILURE);
- }
-}
-
-/**
- * \brief print help message to stderr
- *
- * This function does print a help message to stderr explaining the usage
- * of the executable \p name.
- *
- * \param name The name of this executable.
- */
-static void help(const char *name)
-{
- fprintf(stderr, "Usage: %s [args...]\n", name);
- fprintf(stderr, " -s, --surface Use surface with specified ID\n");
- fprintf(stderr, " -v, --verbose Be verbose\n");
- fprintf(stderr, " -h, --help Display this help message\n");
-}
-
-/**
- * \brief control the IVI surface
- *
- * This function does control the surface \p gdp_surface.
- * Currently the surface is added to its assigned layer,
- * the layer brought into view on the screen and assigned input focus.
- *
- * \param gdp_surfaces The name of this executable.
- */
-static void surface_control(struct gdp_surface_context gdp_surface)
-{
- ilmErrorTypes callResult = ILM_FAILED;
- t_ilm_surface surfaceIdArray[] = {1, 2, 3};
- t_ilm_layer layerIdArray[] = {100, 200, 300};
-
- sd_journal_print(LOG_DEBUG, "surface_control"
- "(surface = %u, layer = %u)\n",
- gdp_surface.id_surface, gdp_surface.id_layer);
-
- surfaceIdArray[2] = gdp_surface.id_surface;
- layerIdArray[2] = gdp_surface.id_layer;
-
- switch(gdp_surface.id_surface) {
- case 1: // Background / Logo
- break;
- case 2: // GDP HMI
- break;
- case 3: // QML Example
- // fall-through
- case 20: // AudioManager PoC
- callResult = ilm_surfaceSetDestinationRectangle(
- gdp_surface.id_surface, 0, 0, screenWidth, screenHeight);
- callResult = ilm_surfaceSetVisibility(
- gdp_surface.id_surface, ILM_TRUE);
- callResult = ilm_surfaceSetOpacity(
- gdp_surface.id_surface, 1.0f);
- callResult = ilm_commitChanges();
- sd_journal_print(LOG_DEBUG, "surface_control - input focus on\n");
- callResult = ilm_UpdateInputEventAcceptanceOn(
- gdp_surface.id_surface,
- ILM_INPUT_DEVICE_POINTER |
- ILM_INPUT_DEVICE_TOUCH |
- ILM_INPUT_DEVICE_KEYBOARD,
- ILM_TRUE);
- callResult = ilm_SetKeyboardFocusOn(gdp_surface.id_surface);
- callResult = ilm_commitChanges();
-
- sd_journal_print(LOG_DEBUG, "surface_control - render order - layer\n");
- callResult = ilm_layerSetRenderOrder(gdp_surface.id_layer,
- surfaceIdArray, 3);
- callResult = ilm_layerSetVisibility(gdp_surface.id_layer,
- ILM_TRUE);
- callResult = ilm_commitChanges();
-
- sd_journal_print(LOG_DEBUG, "surface_control - render order - screen\n");
- callResult = ilm_displaySetRenderOrder((t_ilm_display)screenID,
- layerIdArray, 3);
-
- callResult = ilm_commitChanges();
- break;
- case 30: // Browser PoC
- break;
- case 40: // FSA PoC
- break;
- case 10: // EGL Mock Navigation
- break;
- case 5100: // EGL Input Example
- break;
- default:
- sd_journal_print(LOG_DEBUG,
- "surface_control - unknown surface.\n");
- break;
- } // switch
-}
-
-/**
- * \brief retrieve surface ID(s) that appeared
- *
- * This function will check if, from the list of expected surfaces, any new
- * surface has appeared.
- *
- * \param length The length of the array
- * \param pArray Pointer to array of surface IDs
- */
-static void surfaces_appear_check(t_ilm_int length, t_ilm_surface* pArray)
-{
- if ((length <= 0) && (pArray == NULL))
- return;
-
- // check for appearance
- for (int i = 0; i < length; i++) {
- // check out list of expected surface IDs 'gdp_surfaces'
- for (int count = 0;
- count < sizeof gdp_surfaces / sizeof gdp_surfaces[0]; count++) {
- if (pArray[i] == gdp_surfaces[count].id_surface) {
- // check if surface is already known
- if (ILM_TRUE == gdp_surfaces[count].created)
- continue; // inner for-loop
- // get to know *new* surface
- gdp_surfaces[count].created = ILM_TRUE;
- sd_journal_print(LOG_DEBUG,
- "Debug: new surface id: %i (for layer: %i)\n",
- gdp_surfaces[count].id_surface,
- gdp_surfaces[count].id_layer);
- surface_control(gdp_surfaces[count]);
- }
- } // inner for-loop
- } // outer for-loop
-}
-
-/**
- * \brief retrieve surface ID(s) that disappeared
- *
- * This function will check if, from the list of expected surfaces, any
- * surface has disappeared.
- *
- * \param length The length of the array
- * \param pArray Pointer to array of surface IDs
- */
-static void surfaces_disappear_check(t_ilm_int length, t_ilm_surface* pArray)
-{
- if ((length <= 0) && (pArray == NULL))
- return;
-
- // check for disappearance
- for (int count = 0;
- count < sizeof gdp_surfaces / sizeof gdp_surfaces[0]; count++) {
- t_ilm_bool found = ILM_FALSE;
-
- for (int i = 0; i < length; i++) {
- if (pArray[i] == gdp_surfaces[count].id_surface) {
- found = ILM_TRUE;
- break; // inner for-loop
- }
- } // inner for-loop
-
- if ((ILM_FALSE == found) && (ILM_TRUE == gdp_surfaces[count].created)) {
- gdp_surfaces[count].created = ILM_FALSE;
- sd_journal_print(LOG_DEBUG,
- "Debug: surface id: %i disappeared (from layer: %i)\n",
- gdp_surfaces[count].id_surface,
- gdp_surfaces[count].id_layer);
- }
- } // outer for-loop
-}
-
-/**
- * \brief poll for surface appearance
- *
- * This function gets all surface IDs and compares them with a previous
- * copy to find out if a new surface did appear or an existing vanished.
- */
-static void surface_create_poll(void)
-{
- int count = 0;
- unsigned int* array = NULL;
- ilmErrorTypes callResult = ILM_FAILED;
-
- // retrieve all surface ID(s)
- callResult = ilm_getSurfaceIDs(&count, &array);
- if (ILM_SUCCESS != callResult) {
- sd_journal_print(LOG_ERR,
- "Error: surface_create_poll ilm_getSurfaceIDs - %s.\n",
- ILM_ERROR_STRING(callResult));
- } else if (count != surfacesArrayCount) {
- unsigned int* oldArray = surfacesArray;
-
- // new previously unknown surface(s) appeared
-
- if (surfacesArrayCount < count) {
- sd_journal_print(LOG_DEBUG,
- "Debug: surface_create_poll surfaces = %i (++)\n", count);
- surfaces_appear_check(count, array);
- } else if (surfacesArrayCount > count) {
- sd_journal_print(LOG_DEBUG,
- "Debug: surface_create_poll surfaces = %i (--)\n", count);
- surfaces_disappear_check(count, array);
- }
-
- surfacesArray = array;
- surfacesArrayCount = count;
- array = oldArray;
- }
-
- // free 'array' that had been allocated by ilm_getSurfaceIDs()
- if (NULL != array)
- free(array);
-}
-
-/**
- * \brief main thread
- *
- * This function is the main entry point of this executable.
- * It reads and interprets command line options given by user,
- * creates some layers, waits for surfaces to appear and once
- * it did, assign the surface to a layer and have it rendered.
- */
-int main(int argc, char * const* argv)
-{
- t_ilm_surface surfaceId = 210;
- ilmErrorTypes callResult = ILM_FAILED;
-
- // read and interpret command line options
- while (1){
- struct option opts[] = {
- { "surface", required_argument, NULL, 's' },
- { "verbose", no_argument, NULL, 'v' },
- { "help", no_argument, NULL, 'h' },
- { 0, 0, NULL, 0 }
- };
-
- int c = getopt_long(argc, argv, "s:vh", opts, NULL);
- if (-1 == c) // no more options
- break;
-
- switch(c){
- default:
- sd_journal_print(LOG_ERR,
- "Error: Unrecognized option '%s'\n", optarg);
- break;
- case 's':
- surfaceId = strtol(optarg, NULL, 0);
- break;
- case 'v':
- verbose = 1;
- break;
- case 'h':
- help("gdp-hmi-controller");
- exit(EXIT_FAILURE);
- break;
- }
- }
-
- // initializes the IVI LayerManagement Client
- callResult = ilm_init();
- if (ILM_SUCCESS != callResult) {
- sd_journal_print(LOG_ERR,
- "Error: ilm_init - %s. Exiting.\n",
- ILM_ERROR_STRING(callResult));
- exit(EXIT_FAILURE);
- }
-
- // create all the layers needed
- layer_create();
-
- gRunLoop = 1;
-
- // establish signal handling
- if ((void *)-1 == signal(SIGINT, sig_handler)) {
- sd_journal_print(LOG_ERR, "Error: signal()\n");
- exit(EXIT_FAILURE);
- }
-
- // fill 'surfacesArray' global with already existing surfaces
- callResult = ilm_getSurfaceIDs(&surfacesArrayCount, &surfacesArray);
- if (ILM_SUCCESS != callResult) {
- sd_journal_print(LOG_ERR, "Error: ilm_getSurfaceIDs - %s.\n",
- ILM_ERROR_STRING(callResult));
- } else {
- sd_journal_print(LOG_DEBUG,
- "Debug: main surfaces = %i\n", surfacesArrayCount);
- }
-
- // wait for SIGINT to happen
- while (gRunLoop) {
- /*
- * poll for added surfaces as ilm_surfaceAddNotification()
- * only work for already existing surfaces
- */
- surface_create_poll();
- sleep(1); // was usleep(50)
- }
-
- // destroy the IVI LayerManagement Client
- callResult = ilm_destroy();
- if (ILM_SUCCESS != callResult) {
- sd_journal_print(LOG_ERR,
- "Error: ilm_destroy - %s. Exiting.\n",
- ILM_ERROR_STRING(callResult));
- exit(EXIT_FAILURE);
- }
-
- return EXIT_SUCCESS;
-}
diff --git a/src/gdp-hmi-controller.cpp b/src/gdp-hmi-controller.cpp
new file mode 100644
index 0000000..b9597c9
--- /dev/null
+++ b/src/gdp-hmi-controller.cpp
@@ -0,0 +1,705 @@
+/* SPDXLicenseID: MPL-2.0
+ *
+ * Copyright (C) 2015, GENIVI Alliance
+ *
+ * This file is part of the GENIVI Demo Platform HMI.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License (MPL), 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/.
+ *
+ * For further information see http://www.genivi.org/.
+ *
+ * List of changes:
+ * 23.Jan.2015, Holger Behrens, written
+ * 05.Feb.2015, Holger Behrens, added surface ID '3' handling
+ * 06.Feb.2015, Holger Behrens, added default surfaces (panel, background)
+ * introduced SIGUSR signal handling, pidfile
+ * 09.Feb.2015, Holger Behrens, convert main loop into a glib main loop
+ * 10.Feb.2015, Holger Behrens, added interface to systemd (via dbus-c++)
+ */
+
+/*! \file gdp-hmi-controller.cpp
+ * \brief HMI controller for the GENIVI Demo Platform
+ *
+ * This component implements the HMI controller of the GENIVI Demo Platform
+ * using the GENIVI Alliance wayland-ivi-extension.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <dbus/dbus.h>
+#include <systemd/sd-journal.h>
+
+#include <ilm/ilm_types.h>
+#include <ilm/ilm_client.h>
+#include <ilm/ilm_control.h>
+
+#include "wayland-util.h"
+#include "ivi-controller-client-protocol.h"
+#include "gdp-hmi-surfaces.h"
+#include "gdp-dbus-service.h"
+#include "gdp-dbus-systemd.h"
+
+// definitions
+
+#define DEFAULT_SCREEN_WIDTH 1024
+#define DEFAULT_SCREEN_HEIGHT 768
+#define DEFAULT_PANEL_HEIGHT_LR 68 // low-res (default)
+#define DEFAULT_PANEL_HEIGHT_HR 80 // high-res
+
+// initialize global variables
+
+static int verbose = 0;
+static int gRunLoop = 0;
+static GMainLoop* gMainLoop = NULL;
+static t_ilm_uint screenID = 0;
+static t_ilm_uint screenWidth = DEFAULT_SCREEN_WIDTH;
+static t_ilm_uint screenHeight = DEFAULT_SCREEN_HEIGHT;
+static t_ilm_uint panelHeight = DEFAULT_PANEL_HEIGHT_LR;
+static int surfacesArrayCount = 0;
+static unsigned int* surfacesArray = NULL;
+static const char *GDP_HMI_PID_FILENAME = "/var/run/gdp-hmi-controller.pid";
+
+DBus::Glib::BusDispatcher dispatcher; // dbus-c++ bus dispatcher (glib)
+SystemdService *gSystemdSession; // systemd on session bus (d-bus)
+SystemdService *gSystemd; // systemd on system bus (d-bus)
+
+
+/**
+ * \brief creates a PID file
+ *
+ * This function creates a file and write this process' ID into it.
+ *
+ * \param[IN] progName name of the calling program (i.e., argv[0] or similar)
+ * \param[IN] pidFile name of file to be created (fully qualified)
+ * \return file descriptor referring the file created
+ */
+int create_pid_file(const char *progName, const char *pidFile)
+{
+ int fd;
+ char stringBuffer[256];
+
+ fd = open(pidFile, O_RDWR | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR);
+ if (-1 == fd) {
+ strerror_r(errno, stringBuffer, 256);
+ sd_journal_print(LOG_ERR,
+ "Error: create_pid_file (open) - %s. Exiting.\n", stringBuffer);
+ exit(EXIT_FAILURE);
+ }
+
+ if (-1 == ftruncate(fd, 0)) {
+ strerror_r(errno, stringBuffer, 256);
+ sd_journal_print(LOG_ERR,
+ "Error: create_pid_file (trunc) - %s. Exiting.\n", stringBuffer);
+ exit(EXIT_FAILURE);
+ }
+
+ snprintf(stringBuffer, 256, "%ld\n", (long) getpid());
+ if (write(fd, stringBuffer, strlen(stringBuffer)) != strlen(stringBuffer)) {
+ sd_journal_print(LOG_ERR,
+ "Error: Writing to PID file failed. Exiting.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ return fd;
+}
+
+/**
+ * \brief creates IVI layer
+ *
+ * This function creates the following layers with the given ID:
+ *
+ * Layer Assignment | Layer ID
+ * ------------------: | :------:
+ * panel | 0
+ * launcher | 100
+ * background | 200
+ * AM PoC | 300
+ * Browser PoC | 400
+ * FSA PoC | 500
+ * MockNavigation | 600
+ * InputEventExample | 700
+ *
+ */
+static void layer_create(void)
+{
+ ilmErrorTypes callResult = ILM_FAILED;
+ struct ilmScreenProperties screenProperties;
+ t_ilm_layer layerid = 0;
+ t_ilm_uint* pIDs = NULL;
+ t_ilm_uint numberOfIDs = 0;
+
+ if (!ilm_isInitialized())
+ return;
+
+ callResult = ilm_getScreenIDs(&numberOfIDs, &pIDs);
+ if (ILM_SUCCESS != callResult) {
+ sd_journal_print(LOG_ERR,
+ "Error: layer_create() ilm_getScreenIDs - %s. Exiting.\n",
+ ILM_ERROR_STRING(callResult));
+ exit(EXIT_FAILURE);
+ } else {
+ sd_journal_print(LOG_DEBUG,
+ "Debug: ilm_getScreenIDs - %s. number of screens = %u\n",
+ ILM_ERROR_STRING(callResult), numberOfIDs);
+ for (int i = 0; i < numberOfIDs; i++) {
+ sd_journal_print(LOG_DEBUG, "Debug: Screen ID[%u] = %d\n",
+ i, pIDs[i]);
+ }
+ screenID = 0; // always use screen with the ID 0
+ // (limitation of ivi-shell at time of this writing)
+ }
+ sd_journal_print(LOG_INFO,
+ "Info: layer_create - in screen with ID = %u\n", screenID);
+
+ callResult = ilm_getPropertiesOfScreen(screenID, &screenProperties);
+ if (ILM_SUCCESS != callResult) {
+ sd_journal_print(LOG_ERR,
+ "Error: layer_create() ilm_getPropertiesOfScreen - %s. Exiting.\n",
+ ILM_ERROR_STRING(callResult));
+ exit(EXIT_FAILURE);
+ }
+ screenWidth = screenProperties.screenWidth;
+ screenHeight = screenProperties.screenHeight;
+ sd_journal_print(LOG_INFO,
+ "Info: layer_create - screen size = %u x %u\n",
+ screenWidth, screenHeight);
+ if (0 == screenWidth)
+ screenWidth = DEFAULT_SCREEN_WIDTH;
+ if (0 == screenHeight)
+ screenHeight = DEFAULT_SCREEN_HEIGHT;
+ if (1200 < screenWidth)
+ panelHeight = DEFAULT_PANEL_HEIGHT_HR;
+
+ // create panel layer - layer id '0'
+ callResult = ilm_layerCreateWithDimension(&layerid,
+ screenWidth, panelHeight);
+ if (ILM_SUCCESS != callResult) {
+ sd_journal_print(LOG_ERR,
+ "Error: layer_create (id = %u) - %s\n",
+ layerid, ILM_ERROR_STRING(callResult));
+ } else {
+ sd_journal_print(LOG_DEBUG,
+ "Debug: layer_create (id = %u) - %s (%u x %u)\n",
+ layerid, ILM_ERROR_STRING(callResult),
+ screenWidth, panelHeight);
+ }
+
+ // create all other layers - layer id's '100..700'
+ for(layerid = GDP_LAUNCHER_LAYER_ID; layerid < GDP_MAX_LAYER_ID;
+ layerid += GDP_LAYER_ID_INCR) {
+ callResult = ilm_layerCreateWithDimension(&layerid, screenWidth,
+ (GDP_LAUNCHER_LAYER_ID == layerid) ?
+ screenHeight : (screenHeight - panelHeight));
+ if (ILM_SUCCESS != callResult) {
+ sd_journal_print(LOG_ERR,
+ "Error: layer_create (id = %u) - %s\n",
+ layerid, ILM_ERROR_STRING(callResult));
+ break;
+ } else {
+ sd_journal_print(LOG_DEBUG,
+ "Debug: layer_create (id = %u) - %s (%u x %u)\n",
+ layerid, ILM_ERROR_STRING(callResult), screenWidth,
+ (100 == layerid)?screenHeight:(screenHeight - panelHeight));
+ }
+ } // for-loop
+
+ callResult = ilm_commitChanges();
+ if (ILM_SUCCESS != callResult) {
+ sd_journal_print(LOG_ERR,
+ "Error: layer_create() ilm_commitChanges - %s. Exiting.\n",
+ ILM_ERROR_STRING(callResult));
+ exit(EXIT_FAILURE);
+ }
+}
+
+/**
+ * \brief show the launcher surface
+ *
+ * This function does control the launcher surface given by \p gdp_surface.
+ * Currently the surface is added to its assigned layer with the ID '1'.
+ *
+ * \param gdp_surfaces The GDP surface/layer context used for launcher.
+ */
+static void launcher_show(const struct gdp_surface_context gdp_surface)
+{
+ ilmErrorTypes callResult = ILM_FAILED;
+ t_ilm_surface surfaceIdArray[] = {GDP_LAUNCHER_SURFACE_ID};
+ t_ilm_layer layerIdArray[] = {GDP_LAUNCHER_LAYER_ID};
+
+ sd_journal_print(LOG_DEBUG, "launcher_show"
+ "(surface = %u, layer = %u)\n",
+ gdp_surface.id_surface, gdp_surface.id_layer);
+
+ surfaceIdArray[0] = gdp_surface.id_surface;
+ layerIdArray[0] = gdp_surface.id_layer;
+ callResult = ilm_surfaceSetDestinationRectangle(
+ gdp_surface.id_surface, 0, 0, screenWidth, screenHeight);
+ callResult = ilm_surfaceSetVisibility(
+ gdp_surface.id_surface, ILM_TRUE);
+ callResult = ilm_surfaceSetOpacity(
+ gdp_surface.id_surface, 1.0f);
+ callResult = ilm_commitChanges();
+ sd_journal_print(LOG_DEBUG, "launcher_show - input focus on\n");
+ callResult = ilm_UpdateInputEventAcceptanceOn(
+ gdp_surface.id_surface,
+ ILM_INPUT_DEVICE_POINTER |
+ ILM_INPUT_DEVICE_TOUCH |
+ ILM_INPUT_DEVICE_KEYBOARD,
+ ILM_TRUE);
+ callResult = ilm_SetKeyboardFocusOn(gdp_surface.id_surface);
+ callResult = ilm_commitChanges();
+
+ sd_journal_print(LOG_DEBUG, "launcher_show - render order - layer\n");
+ callResult = ilm_layerSetRenderOrder(gdp_surface.id_layer,
+ surfaceIdArray, 1);
+ callResult = ilm_layerSetVisibility(gdp_surface.id_layer,
+ ILM_TRUE);
+ callResult = ilm_commitChanges();
+
+ sd_journal_print(LOG_DEBUG, "launcher_show - render order - screen\n");
+ callResult = ilm_displaySetRenderOrder((t_ilm_display)screenID,
+ layerIdArray, 1);
+
+ callResult = ilm_commitChanges();
+}
+
+/**
+ * \brief control the IVI surface
+ *
+ * This function does control the surface \p gdp_surface.
+ * Currently the surface is added to its assigned layer,
+ * the layer together with the layer holding the 'panel'
+ * are brought into view on the screen and assigned input focus.
+ *
+ * ID | Surface
+ * :--: | :------
+ * 0 | Panel
+ * 1 | GDP HMI
+ * 2 | Background
+ * 3 | QML Example
+ * 20 | AudioManager PoC
+ * 30 | Browser PoC
+ * 40 | FSA PoC
+ * 10 | EGL Mock Navigation
+ * 5100 | EGL Input Example
+ *
+ * \param gdp_surfaces The GDP surface/layer context to be controlled.
+ */
+static void surface_control(struct gdp_surface_context gdp_surface)
+{
+ ilmErrorTypes callResult = ILM_FAILED;
+ t_ilm_surface surfaceIdArray[] = {GDP_BACKGROUND_SURFACE_ID};
+ t_ilm_layer layerIdArray[] = {GDP_BACKGROUND_LAYER_ID,
+ GDP_PANEL_LAYER_ID};
+
+ sd_journal_print(LOG_DEBUG, "surface_control"
+ "(surface = %u, layer = %u)\n",
+ gdp_surface.id_surface, gdp_surface.id_layer);
+
+ surfaceIdArray[0] = gdp_surface.id_surface;
+ layerIdArray[0] = gdp_surface.id_layer;
+
+ switch(gdp_surface.id_surface) {
+ case GDP_PANEL_SURFACE_ID: // Panel
+ callResult = ilm_surfaceSetDestinationRectangle(
+ gdp_surface.id_surface, 0, 0, screenWidth, panelHeight);
+ callResult = ilm_surfaceSetVisibility(
+ gdp_surface.id_surface, ILM_TRUE);
+ callResult = ilm_surfaceSetOpacity(
+ gdp_surface.id_surface, 1.0f);
+ callResult = ilm_commitChanges();
+ sd_journal_print(LOG_DEBUG, "surface_control (0) - input focus on\n");
+ callResult = ilm_UpdateInputEventAcceptanceOn(
+ gdp_surface.id_surface,
+ ILM_INPUT_DEVICE_POINTER |
+ ILM_INPUT_DEVICE_TOUCH |
+ ILM_INPUT_DEVICE_KEYBOARD,
+ ILM_TRUE);
+ callResult = ilm_SetKeyboardFocusOn(gdp_surface.id_surface);
+ callResult = ilm_commitChanges();
+ sd_journal_print(LOG_DEBUG, "surface_control - render order - layer\n");
+ callResult = ilm_layerSetDestinationRectangle(gdp_surface.id_layer,
+ 0, screenHeight - panelHeight, screenWidth, panelHeight);
+ callResult = ilm_layerSetRenderOrder(gdp_surface.id_layer,
+ surfaceIdArray, 1);
+ callResult = ilm_layerSetVisibility(gdp_surface.id_layer,
+ ILM_TRUE);
+ callResult = ilm_commitChanges();
+ break;
+ case GDP_LAUNCHER_SURFACE_ID: // GDP HMI / Launcher
+ launcher_show(gdp_surface);
+ break;
+ case GDP_BACKGROUND_SURFACE_ID: // Background / Logo
+ // fall-through
+ case QML_EXAMPLE_SURFACE_ID: // QML Example
+ // fall-through
+ case AM_DEMO_SURFACE_ID: // AudioManager PoC/Demo
+ // fall-through
+ case BROWSER_POC_SURFACE_ID: // Browser PoC
+ // fall-through
+ case FSA_SURFACE_ID: // FSA PoC
+ // fall-through
+ case MOCK_NAVIGATION_SURFACE_ID: // EGL Mock Navigation
+ // fall-through
+ case INPUT_EVENT_EXAMPLE_SURFACE_ID: // EGL Input Example
+ callResult = ilm_surfaceSetDestinationRectangle(
+ gdp_surface.id_surface, 0, 0, screenWidth, screenHeight - panelHeight);
+ callResult = ilm_surfaceSetVisibility(
+ gdp_surface.id_surface, ILM_TRUE);
+ callResult = ilm_surfaceSetOpacity(
+ gdp_surface.id_surface, 1.0f);
+ callResult = ilm_commitChanges();
+ sd_journal_print(LOG_DEBUG, "surface_control - input focus on\n");
+ callResult = ilm_UpdateInputEventAcceptanceOn(
+ gdp_surface.id_surface,
+ ILM_INPUT_DEVICE_POINTER |
+ ILM_INPUT_DEVICE_TOUCH |
+ ILM_INPUT_DEVICE_KEYBOARD,
+ ILM_TRUE);
+ callResult = ilm_SetKeyboardFocusOn(gdp_surface.id_surface);
+ callResult = ilm_commitChanges();
+
+ sd_journal_print(LOG_DEBUG, "surface_control - render order - layer\n");
+ callResult = ilm_layerSetRenderOrder(gdp_surface.id_layer,
+ surfaceIdArray, 1);
+ callResult = ilm_layerSetVisibility(gdp_surface.id_layer,
+ ILM_TRUE);
+ callResult = ilm_commitChanges();
+
+ sd_journal_print(LOG_DEBUG, "surface_control - render order - screen\n");
+ callResult = ilm_displaySetRenderOrder((t_ilm_display)screenID,
+ layerIdArray, 2);
+
+ callResult = ilm_commitChanges();
+ break;
+ default:
+ sd_journal_print(LOG_DEBUG,
+ "surface_control - unknown surface.\n");
+ return;
+ break;
+ } // switch
+}
+
+/**
+ * \brief retrieve surface ID(s) that appeared
+ *
+ * This function will check if, from the list of expected surfaces, any new
+ * surface has appeared.
+ *
+ * \param length The length of the array
+ * \param pArray Pointer to array of surface IDs
+ */
+static void surfaces_appear_check(t_ilm_int length, t_ilm_surface* pArray)
+{
+ if ((length <= 0) && (pArray == NULL))
+ return;
+
+ // check for appearance
+ for (int i = 0; i < length; i++) {
+ // check out list of expected surface IDs 'gdp_surfaces'
+ for (int count = 0;
+ count < sizeof gdp_surfaces / sizeof gdp_surfaces[0]; count++) {
+ if (pArray[i] == gdp_surfaces[count].id_surface) {
+ // check if surface is already known
+ if (ILM_TRUE == gdp_surfaces[count].created)
+ continue; // inner for-loop
+ // get to know *new* surface
+ gdp_surfaces[count].created = ILM_TRUE;
+ sd_journal_print(LOG_DEBUG,
+ "Debug: new surface id: %i (for layer: %i)\n",
+ gdp_surfaces[count].id_surface,
+ gdp_surfaces[count].id_layer);
+ surface_control(gdp_surfaces[count]);
+ }
+ } // inner for-loop
+ } // outer for-loop
+}
+
+/**
+ * \brief retrieve surface ID(s) that disappeared
+ *
+ * This function will check if, from the list of expected surfaces, any
+ * surface has disappeared.
+ *
+ * \param length The length of the array
+ * \param pArray Pointer to array of surface IDs
+ */
+static void surfaces_disappear_check(t_ilm_int length, t_ilm_surface* pArray)
+{
+ if ((length <= 0) && (pArray == NULL))
+ return;
+
+ // check for disappearance
+ for (int count = 0;
+ count < sizeof gdp_surfaces / sizeof gdp_surfaces[0]; count++) {
+ t_ilm_bool found = ILM_FALSE;
+
+ for (int i = 0; i < length; i++) {
+ if (pArray[i] == gdp_surfaces[count].id_surface) {
+ found = ILM_TRUE;
+ break; // inner for-loop
+ }
+ } // inner for-loop
+
+ if ((ILM_FALSE == found) && (ILM_TRUE == gdp_surfaces[count].created)) {
+ gdp_surfaces[count].created = ILM_FALSE;
+ sd_journal_print(LOG_DEBUG,
+ "Debug: surface id: %i disappeared (from layer: %i)\n",
+ gdp_surfaces[count].id_surface,
+ gdp_surfaces[count].id_layer);
+ }
+ } // outer for-loop
+}
+
+/**
+ * \brief poll for surface appearance
+ *
+ * This function gets all surface IDs and compares them with a previous
+ * copy to find out if a new surface did appear or an existing vanished.
+ */
+static gboolean surface_create_poll(gpointer data)
+{
+ int count = 0;
+ unsigned int* array = NULL;
+ ilmErrorTypes callResult = ILM_FAILED;
+
+ // retrieve all surface ID(s)
+ callResult = ilm_getSurfaceIDs(&count, &array);
+ if (ILM_SUCCESS != callResult) {
+ sd_journal_print(LOG_ERR,
+ "Error: surface_create_poll ilm_getSurfaceIDs - %s.\n",
+ ILM_ERROR_STRING(callResult));
+ } else if (count != surfacesArrayCount) {
+ unsigned int* oldArray = surfacesArray;
+
+ // new previously unknown surface(s) appeared
+
+ if (surfacesArrayCount < count) {
+ sd_journal_print(LOG_DEBUG,
+ "Debug: surface_create_poll surfaces = %i (++)\n", count);
+ surfaces_appear_check(count, array);
+ } else if (surfacesArrayCount > count) {
+ sd_journal_print(LOG_DEBUG,
+ "Debug: surface_create_poll surfaces = %i (--)\n", count);
+ surfaces_disappear_check(count, array);
+ }
+
+ surfacesArray = array;
+ surfacesArrayCount = count;
+ array = oldArray;
+ }
+
+ // free 'array' that had been allocated by ilm_getSurfaceIDs()
+ if (NULL != array)
+ free(array);
+
+ return TRUE;
+}
+
+/**
+ * \brief signal handler
+ *
+ * This function shall handle all signals of type 'SIGINT', 'SIGTERM',
+ * 'SIGUSR1' and 'SIGUSR2'.
+ *
+ */
+static void sig_handler(int signo)
+{
+ sd_journal_print(LOG_DEBUG, "Debug: sig_handler() - %d\n", signo);
+
+ switch(signo) {
+ case SIGINT:
+ sd_journal_print(LOG_DEBUG, "Debug: Interrupt from keyboard.\n");
+ // fall-through
+ case SIGTERM:
+ g_main_loop_quit(gMainLoop); // stop the main loop in main()
+ break;
+ case SIGUSR1:
+ if (ILM_TRUE == gdp_surfaces[1].created) {
+ launcher_show(gdp_surfaces[1]);
+ }
+ sd_journal_print(LOG_DEBUG, "Debug: show launcher (%s)\n",
+ (ILM_TRUE == gdp_surfaces[1].created) ? "true" : "false");
+ break;
+ case SIGUSR2:
+ if (ILM_TRUE == gdp_surfaces[2].created) {
+ surface_control(gdp_surfaces[2]);
+ }
+ sd_journal_print(LOG_DEBUG, "Debug: show background\n");
+ break;
+ default:
+ sd_journal_print(LOG_DEBUG, "Debug: signal (%d) unknown\n", signo);
+ break;
+ } // switch
+}
+
+/**
+ * \brief print help message to stderr
+ *
+ * This function does print a help message to stderr explaining the usage
+ * of the executable \p name.
+ *
+ * \param name The name of this executable.
+ */
+static void help(const char *name)
+{
+ fprintf(stderr, "Usage: %s [args...]\n", name);
+ fprintf(stderr, " -s, --surface Use surface with specified ID\n");
+ fprintf(stderr, " -v, --verbose Be verbose\n");
+ fprintf(stderr, " -h, --help Display this help message\n");
+}
+
+/**
+ * \brief main thread
+ *
+ * This function is the main entry point of this executable.
+ * It reads and interprets command line options given by user,
+ * creates some layers, waits for surfaces to appear and once
+ * it did, assign the surface to a layer and have it rendered.
+ */
+int main(int argc, char * const* argv)
+{
+ int fd = -1;
+ int rtn = -1;
+ t_ilm_surface surfaceId = 0;
+ ilmErrorTypes callResult = ILM_FAILED;
+
+ sd_journal_print(LOG_INFO, "GDP HMI Controller (main)\n");
+
+ // establish signal handling
+ if ((void *)-1 == signal(SIGTERM, sig_handler)) {
+ sd_journal_print(LOG_ERR, "Error: signal(SIGTERM)\n");
+ exit(EXIT_FAILURE);
+ }
+ if ((void *)-1 == signal(SIGINT, sig_handler)) {
+ sd_journal_print(LOG_ERR, "Error: signal(SIGINT)\n");
+ exit(EXIT_FAILURE);
+ }
+ if ((void *)-1 == signal(SIGUSR1, sig_handler)) {
+ sd_journal_print(LOG_ERR, "Error: signal(SIGUSR1)\n");
+ exit(EXIT_FAILURE);
+ }
+ if ((void *)-1 == signal(SIGUSR2, sig_handler)) {
+ sd_journal_print(LOG_ERR, "Error: signal(SIGUSR2)\n");
+ exit(EXIT_FAILURE);
+ }
+
+ // read and interpret command line options
+ while (1){
+ struct option opts[] = {
+ { "surface", required_argument, NULL, 's' },
+ { "verbose", no_argument, NULL, 'v' },
+ { "help", no_argument, NULL, 'h' },
+ { 0, 0, NULL, 0 }
+ };
+
+ int c = getopt_long(argc, argv, "s:vh", opts, NULL);
+ if (-1 == c) // no more options
+ break;
+
+ switch(c){
+ default:
+ sd_journal_print(LOG_ERR,
+ "Error: Unrecognized option '%s'\n", optarg);
+ break;
+ case 's':
+ surfaceId = strtol(optarg, NULL, 0);
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case 'h':
+ help("gdp-hmi-controller");
+ exit(EXIT_FAILURE);
+ break;
+ }
+ }
+
+ fd = create_pid_file(argv[0], GDP_HMI_PID_FILENAME);
+
+ /*
+ * make ourselves available on the d-bus session bus
+ *
+ * currently this interface is only used by the launcher to tell the
+ * controller (us), to power off, which application (systemd unit) to
+ * launch or give focus and bring to front/into view.
+ *
+ * The 'home' button activation is signaled via USR1.
+ */
+
+ DBus::default_dispatcher = &dispatcher;
+ dispatcher.attach(NULL);
+ DBus::Connection conn = DBus::Connection::SessionBus();
+ conn.request_name(GDP_DBUS_SERVICE_NAME);
+ HmiService service(conn);
+ sd_journal_print(LOG_INFO, "GDP HMI Controller (dbus) - %s\n",
+ GDP_DBUS_SERVICE_NAME);
+ // make a connection to systemd on the session bus
+ DBus::Connection sessionBus = DBus::Connection::SessionBus();
+ SystemdService systemdSession(sessionBus,
+ SYSTEMD_DBUS_SERVICE_PATH, SYSTEMD_DBUS_SERVICE_NAME);
+ gSystemdSession = &systemdSession;
+ std::string systemdVersion = systemdSession.Version();
+ sd_journal_print(LOG_INFO, "GDP HMI Control -> systemd (session)"
+ " systemd version: %s\n", systemdVersion.c_str());
+ // make a connection to systemd on the system bus
+ DBus::Connection systemBus = DBus::Connection::SystemBus();
+ SystemdService systemd(systemBus,
+ SYSTEMD_DBUS_SERVICE_PATH, SYSTEMD_DBUS_SERVICE_NAME);
+ gSystemd = &systemd;
+ systemdVersion = systemd.Version();
+ sd_journal_print(LOG_INFO, "GDP HMI Control -> systemd (system)"
+ " systemd version: %s\n", systemdVersion.c_str());
+
+ // initializes the IVI LayerManagement Client
+ callResult = ilm_init();
+ if (ILM_SUCCESS != callResult) {
+ sd_journal_print(LOG_ERR,
+ "Error: ilm_init - %s. Exiting.\n",
+ ILM_ERROR_STRING(callResult));
+ exit(EXIT_FAILURE);
+ }
+
+ // create all the layers needed
+ layer_create();
+
+ // fill 'surfacesArray' global with already existing surfaces
+ callResult = ilm_getSurfaceIDs(&surfacesArrayCount, &surfacesArray);
+ if (ILM_SUCCESS != callResult) {
+ sd_journal_print(LOG_ERR, "Error: ilm_getSurfaceIDs - %s.\n",
+ ILM_ERROR_STRING(callResult));
+ } else {
+ sd_journal_print(LOG_DEBUG,
+ "Debug: main surfaces = %i\n", surfacesArrayCount);
+ }
+
+ // go into a loop, poll for surfaces every second
+ gMainLoop = g_main_loop_new (NULL, FALSE);
+ g_timeout_add_seconds(1, surface_create_poll, NULL);
+ g_main_loop_run(gMainLoop);
+
+ // close and delete PID file
+ if (-1 != fd)
+ close (fd);
+ unlink (GDP_HMI_PID_FILENAME);
+
+ // destroy the IVI LayerManagement Client
+ callResult = ilm_destroy();
+ if (ILM_SUCCESS != callResult) {
+ sd_journal_print(LOG_ERR,
+ "Error: ilm_destroy - %s. Exiting.\n",
+ ILM_ERROR_STRING(callResult));
+ exit(EXIT_FAILURE);
+ }
+
+ return EXIT_SUCCESS;
+}