Compare commits
10 Commits
94ee66acd7
...
4ab5a162c4
Author | SHA1 | Date | |
---|---|---|---|
4ab5a162c4 | |||
|
e7caeb4d49 | ||
|
6496f8e360 | ||
|
8fa72b4f43 | ||
|
e2b6985d87 | ||
|
cf77993f3c | ||
|
618a014100 | ||
|
efb9d8bc6f | ||
|
658005da61 | ||
|
e940b8036e |
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,6 +4,7 @@
|
|||||||
lib/
|
lib/
|
||||||
bin/
|
bin/
|
||||||
.idea/
|
.idea/
|
||||||
|
build/
|
||||||
|
|
||||||
CMakeLists.txt.user
|
CMakeLists.txt.user
|
||||||
cmake-build-*/
|
cmake-build-*/
|
||||||
|
@ -1,16 +1,23 @@
|
|||||||
cmake_minimum_required(VERSION 3.5.1)
|
cmake_minimum_required(VERSION 3.5.1)
|
||||||
|
|
||||||
|
set (openauto_VERSION_MAJOR 2)
|
||||||
|
set (openauto_VERSION_MINOR 1)
|
||||||
|
set (openauto_VERSION_PATCH 0)
|
||||||
|
|
||||||
|
project(openauto
|
||||||
|
VERSION ${openauto_VERSION_MAJOR}.${openauto_VERSION_MINOR}.${openauto_VERSION_PATCH}
|
||||||
|
LANGUAGES CXX)
|
||||||
|
|
||||||
find_program(CCACHE_PROGRAM ccache)
|
find_program(CCACHE_PROGRAM ccache)
|
||||||
if(CCACHE_PROGRAM)
|
if(CCACHE_PROGRAM)
|
||||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
|
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
project(openauto CXX)
|
|
||||||
|
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
set(CMAKE_AUTOUIC ON)
|
set(CMAKE_AUTOUIC ON)
|
||||||
set(CMAKE_AUTORCC ON)
|
set(CMAKE_AUTORCC ON)
|
||||||
|
|
||||||
|
set(base_directory ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib)
|
set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib)
|
||||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib)
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib)
|
||||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib)
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib)
|
||||||
@ -40,8 +47,10 @@ find_package(Protobuf REQUIRED)
|
|||||||
find_package(OpenSSL REQUIRED)
|
find_package(OpenSSL REQUIRED)
|
||||||
find_package(rtaudio REQUIRED)
|
find_package(rtaudio REQUIRED)
|
||||||
find_package(aasdk REQUIRED)
|
find_package(aasdk REQUIRED)
|
||||||
|
find_package(h264 REQUIRED)
|
||||||
find_package(Threads)
|
find_package(Threads)
|
||||||
|
|
||||||
|
include(${base_directory}/cmake_modules/gitversion.cmake)
|
||||||
if(RPI_BUILD)
|
if(RPI_BUILD)
|
||||||
find_package(libomx)
|
find_package(libomx)
|
||||||
endif()
|
endif()
|
||||||
@ -65,7 +74,7 @@ if(GST_BUILD)
|
|||||||
if(RPI_MODEL EQUAL 17)
|
if(RPI_MODEL EQUAL 17)
|
||||||
message("Raspberry Pi 4 Found")
|
message("Raspberry Pi 4 Found")
|
||||||
add_definitions(-DPI4)
|
add_definitions(-DPI4)
|
||||||
endif(RPI_REVISION EQUAL 17)
|
endif(RPI_MODEL EQUAL 17)
|
||||||
endif(RPI_BUILD)
|
endif(RPI_BUILD)
|
||||||
message(STATUS "${GST_LIBRARIES}")
|
message(STATUS "${GST_LIBRARIES}")
|
||||||
endif(GST_BUILD)
|
endif(GST_BUILD)
|
||||||
@ -77,3 +86,43 @@ include_directories(${BTSERVICE_PROTO_INCLUDE_DIRS})
|
|||||||
add_subdirectory(openauto)
|
add_subdirectory(openauto)
|
||||||
add_subdirectory(autoapp)
|
add_subdirectory(autoapp)
|
||||||
add_dependencies(autoapp btservice_proto)
|
add_dependencies(autoapp btservice_proto)
|
||||||
|
|
||||||
|
set (openauto_VERSION_PATCH ${_build_version})
|
||||||
|
set (openauto_VERSION_STRING ${openauto_VERSION_MAJOR}.${openauto_VERSION_MINOR}.${openauto_VERSION_PATCH})
|
||||||
|
set_target_properties(openauto PROPERTIES VERSION ${openauto_VERSION_STRING}
|
||||||
|
SOVERSION ${openauto_VERSION_MAJOR})
|
||||||
|
message(INFO " Project Version: ${openauto_VERSION_STRING}")
|
||||||
|
|
||||||
|
install(DIRECTORY lib DESTINATION lib COMPONENT libraries)
|
||||||
|
install(DIRECTORY include DESTINATION include COMPONENT headers)
|
||||||
|
install(DIRECTORY bin DESTINATION bin COMPONENT applications)
|
||||||
|
|
||||||
|
SET(CPACK_GENERATOR "DEB")
|
||||||
|
SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "OpenDsh") #required
|
||||||
|
SET(CPACK_PACKAGE_VENDOR "OpenDsh")
|
||||||
|
set(CPACK_PACKAGE_VERSION ${openauto_VERSION_STRING})
|
||||||
|
set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT)
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
|
||||||
|
set(CPACK_COMPONENTS_ALL applications libraries headers Unspecified)
|
||||||
|
set(CPACK_COMPONENT_APPLICATIONS_DISPLAY_NAME "Applications")
|
||||||
|
set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries")
|
||||||
|
set(CPACK_COMPONENT_HEADERS_DISPLAY_NAME "C++ Headers")
|
||||||
|
set(CPACK_COMPONENT_APPLICATIONS_DESCRIPTION
|
||||||
|
"Applications provided by OpenAuto")
|
||||||
|
set(CPACK_COMPONENT_LIBRARIES_DESCRIPTION
|
||||||
|
"Static libraries used to build programs with OpenAuto")
|
||||||
|
set(CPACK_COMPONENT_HEADERS_DESCRIPTION
|
||||||
|
"C/C++ header files for use with OpenAuto")
|
||||||
|
set(CPACK_COMPONENT_LIBRARIES_GROUP "Development")
|
||||||
|
set(CPACK_COMPONENT_HEADERS_GROUP "Development")
|
||||||
|
set(CPACK_COMPONENT_GROUP_DEVELOPMENT_EXPANDED ON)
|
||||||
|
set(CPACK_COMPONENT_GROUP_DEVELOPMENT_DESCRIPTION
|
||||||
|
"All of the tools you'll ever need to develop software")
|
||||||
|
set(CPACK_COMPONENT_HEADERS_DEPENDS libraries)
|
||||||
|
set(CPACK_COMPONENT_APPLICATIONS_DEPENDS libraries)
|
||||||
|
set(CPACK_ALL_INSTALL_TYPES Full Developer)
|
||||||
|
set(CPACK_INSTALL_TYPE_FULL_DISPLAY_NAME "Everything")
|
||||||
|
set(CPACK_COMPONENT_LIBRARIES_INSTALL_TYPES Developer Full)
|
||||||
|
set(CPACK_COMPONENT_HEADERS_INSTALL_TYPES Developer Full)
|
||||||
|
set(CPACK_COMPONENT_APPLICATIONS_INSTALL_TYPES Full)
|
||||||
|
INCLUDE(CPack)
|
@ -17,6 +17,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <QtWebSockets/QWebSocket>
|
||||||
|
#include <QDBusInterface>
|
||||||
|
#include <QDBusConnection>
|
||||||
|
#include <QDBusReply>
|
||||||
|
#include <QDBusMessage>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
#include "autoapp/UI/MainWindow.hpp"
|
#include "autoapp/UI/MainWindow.hpp"
|
||||||
#include "ui_mainwindow.h"
|
#include "ui_mainwindow.h"
|
||||||
|
|
||||||
@ -26,20 +33,141 @@ namespace ui
|
|||||||
{
|
{
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget *parent)
|
MainWindow::MainWindow(QWidget *parent)
|
||||||
: QMainWindow(parent)
|
: QMainWindow(parent), ui_(new Ui::MainWindow), webSocket(new QWebSocket),
|
||||||
, ui_(new Ui::MainWindow)
|
reconnectTimer(new QTimer(this)),
|
||||||
|
metadataTimer(new QTimer(this)),
|
||||||
|
shuttingDown(false)
|
||||||
{
|
{
|
||||||
ui_->setupUi(this);
|
ui_->setupUi(this);
|
||||||
connect(ui_->pushButtonSettings, &QPushButton::clicked, this, &MainWindow::openSettings);
|
connect(ui_->pushButtonSettings, &QPushButton::clicked, this, &MainWindow::openSettings);
|
||||||
connect(ui_->pushButtonExit, &QPushButton::clicked, this, &MainWindow::exit);
|
connect(ui_->pushButtonExit, &QPushButton::clicked, this, &MainWindow::exit);
|
||||||
connect(ui_->pushButtonToggleCursor, &QPushButton::clicked, this, &MainWindow::toggleCursor);
|
connect(ui_->pushButtonToggleCursor, &QPushButton::clicked, this, &MainWindow::toggleCursor);
|
||||||
connect(ui_->pushButtonWirelessConnection, &QPushButton::clicked, this, &MainWindow::openConnectDialog);
|
connect(ui_->pushButtonWirelessConnection, &QPushButton::clicked, this, &MainWindow::openConnectDialog);
|
||||||
|
|
||||||
|
// BT NOW PLAYING UPDATE
|
||||||
|
connect(metadataTimer, &QTimer::timeout, this, &MainWindow::updateNowPlaying);
|
||||||
|
metadataTimer->start(1000); // refresh every 5 seconds
|
||||||
|
|
||||||
|
// RADIO WEBSOCKET STUFF
|
||||||
|
reconnectTimer->setSingleShot(true);
|
||||||
|
reconnectTimer->setInterval(3000);
|
||||||
|
|
||||||
|
connect(reconnectTimer, &QTimer::timeout, this, &MainWindow::connectWebSocket);
|
||||||
|
|
||||||
|
connect(webSocket, &QWebSocket::connected, this, [this]()
|
||||||
|
{
|
||||||
|
qDebug() << "WebSocket connected";
|
||||||
|
webSocket->sendTextMessage(QStringLiteral("Hello from MainWindow WebSocket!")); });
|
||||||
|
|
||||||
|
connect(webSocket, &QWebSocket::textMessageReceived, this, [this](const QString &message)
|
||||||
|
{
|
||||||
|
qDebug() << "Message received:" << message;
|
||||||
|
handleIncomingMessage(message); });
|
||||||
|
|
||||||
|
connect(webSocket, &QWebSocket::disconnected, this, [this]()
|
||||||
|
{
|
||||||
|
qDebug() << "WebSocket disconnected";
|
||||||
|
if (!shuttingDown) {
|
||||||
|
qDebug() << "Attempting to reconnect in 3 seconds...";
|
||||||
|
reconnectTimer->start();
|
||||||
|
} });
|
||||||
|
|
||||||
|
connect(webSocket, QOverload<QAbstractSocket::SocketError>::of(&QWebSocket::error),
|
||||||
|
this, [this](QAbstractSocket::SocketError)
|
||||||
|
{ qDebug() << "WebSocket error:" << webSocket->errorString(); });
|
||||||
|
|
||||||
|
connectWebSocket();
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::~MainWindow()
|
MainWindow::~MainWindow()
|
||||||
{
|
{
|
||||||
|
shuttingDown = true;
|
||||||
|
webSocket->abort();
|
||||||
|
webSocket->deleteLater();
|
||||||
delete ui_;
|
delete ui_;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void f1x::openauto::autoapp::ui::MainWindow::updateBtNowPlaying()
|
||||||
|
{
|
||||||
|
QDBusInterface manager(
|
||||||
|
"org.bluez",
|
||||||
|
"/",
|
||||||
|
"org.freedesktop.DBus.ObjectManager",
|
||||||
|
QDBusConnection::systemBus());
|
||||||
|
|
||||||
|
if (!manager.isValid())
|
||||||
|
{
|
||||||
|
qDebug() << "Failed to connect to BlueZ D-Bus";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDBusReply<QVariantMap> reply = manager.call("GetManagedObjects");
|
||||||
|
|
||||||
|
if (!reply.isValid())
|
||||||
|
{
|
||||||
|
qDebug() << "D-Bus call failed:" << reply.error().message();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap allObjects = reply.value();
|
||||||
|
|
||||||
|
for (auto it = allObjects.begin(); it != allObjects.end(); ++it)
|
||||||
|
{
|
||||||
|
QString path = it.key();
|
||||||
|
QVariantMap interfaces = it.value().toMap();
|
||||||
|
|
||||||
|
if (interfaces.contains("org.bluez.MediaPlayer1"))
|
||||||
|
{
|
||||||
|
qDebug() << "Found MediaPlayer at:" << path;
|
||||||
|
|
||||||
|
QDBusInterface mediaPlayer(
|
||||||
|
"org.bluez",
|
||||||
|
path,
|
||||||
|
"org.freedesktop.DBus.Properties",
|
||||||
|
QDBusConnection::systemBus());
|
||||||
|
|
||||||
|
QDBusReply<QVariant> trackReply = mediaPlayer.call("Get", "org.bluez.MediaPlayer1", "Track");
|
||||||
|
if (trackReply.isValid())
|
||||||
|
{
|
||||||
|
QVariantMap track = trackReply.value().toMap();
|
||||||
|
QString artist = track["Artist"].toString();
|
||||||
|
QString title = track["Title"].toString();
|
||||||
|
QString album = track["Album"].toString();
|
||||||
|
|
||||||
|
QString status = statusReply.value().toString();
|
||||||
|
|
||||||
|
qDebug() << "Now playing:" << artist << "-" << title << "from" << album;
|
||||||
|
qDebug() << "Status:" << status;
|
||||||
|
|
||||||
|
if (status == "Playing")
|
||||||
|
{
|
||||||
|
ui_->stackedWidget->setCurrentIndex(0);
|
||||||
|
ui_->btSongName->setText(title);
|
||||||
|
ui_->btArtistName->setText(artist);
|
||||||
|
ui_->btAlbumName->setText(album);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ui_->stackedWidget->setCurrentIndex(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void f1x::openauto::autoapp::ui::MainWindow::connectWebSocket()
|
||||||
|
{
|
||||||
|
QUrl url(QStringLiteral("ws://127.0.0.1:5000")); // Change to your real server
|
||||||
|
qDebug() << "Connecting to WebSocket:" << url;
|
||||||
|
webSocket->open(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
void f1x::openauto::autoapp::ui::MainWindow::handleIncomingMessage(const QString &message)
|
||||||
|
{
|
||||||
|
// Your custom message processing logic here
|
||||||
|
qDebug() << "[Handler] Processing message:" << message;
|
||||||
|
}
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>800</width>
|
<width>1046</width>
|
||||||
<height>480</height>
|
<height>571</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@ -18,41 +18,436 @@
|
|||||||
color: rgb(238, 238, 236);</string>
|
color: rgb(238, 238, 236);</string>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="centralwidget">
|
<widget class="QWidget" name="centralwidget">
|
||||||
<widget class="QLabel" name="labelWaitingForDevice">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QStackedWidget" name="stackedWidget">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>1024</width>
|
||||||
|
<height>500</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>1024</width>
|
||||||
|
<height>500</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="page">
|
||||||
|
<widget class="QFrame" name="verticalFrame">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>290</x>
|
<x>0</x>
|
||||||
<y>30</y>
|
<y>0</y>
|
||||||
<width>281</width>
|
<width>1021</width>
|
||||||
<height>41</height>
|
<height>500</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>500</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>1024</width>
|
||||||
|
<height>500</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item alignment="Qt::AlignVCenter">
|
||||||
|
<widget class="QFrame" name="verticalFrame">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
<item alignment="Qt::AlignHCenter">
|
||||||
|
<widget class="QWidget" name="btNowPlaying" native="true">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>16777215</width>
|
||||||
|
<height>300</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>200</width>
|
||||||
|
<height>200</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>200</width>
|
||||||
|
<height>200</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string><html><head/><body><p><span style=" font-size:22pt; font-weight:600; font-style:italic; color:#3465a4;">Waiting for device...</span></p></body></html></string>
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="pixmap">
|
||||||
|
<pixmap resource="../assets/resources.qrc">:/bluetooth.png</pixmap>
|
||||||
|
</property>
|
||||||
|
<property name="scaledContents">
|
||||||
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QLabel" name="label">
|
</item>
|
||||||
|
<item alignment="Qt::AlignHCenter">
|
||||||
|
<widget class="QWidget" name="widget" native="true">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>16777215</width>
|
||||||
|
<height>300</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_9">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_8">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>60</width>
|
||||||
|
<height>60</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="pixmap">
|
||||||
|
<pixmap resource="../assets/resources.qrc">:/song.png</pixmap>
|
||||||
|
</property>
|
||||||
|
<property name="scaledContents">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="btSongName">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>24</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Lorem Ipsum Dorem</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_9">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>60</width>
|
||||||
|
<height>60</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>60</width>
|
||||||
|
<height>60</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="pixmap">
|
||||||
|
<pixmap resource="../assets/resources.qrc">:/artist.png</pixmap>
|
||||||
|
</property>
|
||||||
|
<property name="scaledContents">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="btArtistName">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>16</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Example Artist</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_10">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>60</width>
|
||||||
|
<height>60</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="pixmap">
|
||||||
|
<pixmap resource="../assets/resources.qrc">:/album.png</pixmap>
|
||||||
|
</property>
|
||||||
|
<property name="scaledContents">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="btAlbumName">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>16</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Example Album</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item alignment="Qt::AlignHCenter|Qt::AlignBottom">
|
||||||
|
<widget class="QLabel" name="btRadioScreen">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>16777215</width>
|
||||||
|
<height>50</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>24</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>ABCD,EFGH</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="page_2">
|
||||||
|
<widget class="QFrame" name="horizontalFrame">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>180</x>
|
<x>0</x>
|
||||||
<y>20</y>
|
<y>0</y>
|
||||||
<width>101</width>
|
<width>1024</width>
|
||||||
<height>101</height>
|
<height>550</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>550</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>1024</width>
|
||||||
|
<height>550</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item alignment="Qt::AlignHCenter|Qt::AlignVCenter">
|
||||||
|
<widget class="QWidget" name="horizontalWidget" native="true">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="radioIcon">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>200</width>
|
||||||
|
<height>200</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>200</width>
|
||||||
|
<height>200</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string><html><head/><body><p><img src=":/ico_androidauto.png"/></p></body></html></string>
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="pixmap">
|
||||||
|
<pixmap resource="../assets/resources.qrc">:/radio.png</pixmap>
|
||||||
|
</property>
|
||||||
|
<property name="scaledContents">
|
||||||
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="radioScreen">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>40</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>ABCD,EFGH</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="radioPreset">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>50</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>16777215</width>
|
||||||
|
<height>50</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>20</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>0</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="radioSecondLine">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>16777215</width>
|
||||||
|
<height>50</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>16</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Tuner List</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item alignment="Qt::AlignHCenter|Qt::AlignBottom">
|
||||||
|
<widget class="QWidget" name="horizontalWidget" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>1024</width>
|
||||||
|
<height>30</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>1024</width>
|
||||||
|
<height>50</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="baseSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>30</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pushButtonExit">
|
||||||
|
<property name="text">
|
||||||
|
<string>Exit</string>
|
||||||
|
</property>
|
||||||
|
<property name="autoDefault">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
<widget class="QPushButton" name="pushButtonSettings">
|
<widget class="QPushButton" name="pushButtonSettings">
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>630</x>
|
|
||||||
<y>330</y>
|
|
||||||
<width>161</width>
|
|
||||||
<height>41</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Settings</string>
|
<string>Settings</string>
|
||||||
</property>
|
</property>
|
||||||
@ -63,160 +458,9 @@ color: rgb(238, 238, 236);</string>
|
|||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QPushButton" name="pushButtonExit">
|
</item>
|
||||||
<property name="geometry">
|
<item>
|
||||||
<rect>
|
|
||||||
<x>630</x>
|
|
||||||
<y>380</y>
|
|
||||||
<width>161</width>
|
|
||||||
<height>41</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Exit</string>
|
|
||||||
</property>
|
|
||||||
<property name="autoDefault">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
<widget class="QLabel" name="labelPluginDeviceText">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>340</x>
|
|
||||||
<y>70</y>
|
|
||||||
<width>301</width>
|
|
||||||
<height>31</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string><html><head/><body><p><span style=" font-style:italic; color:#eeeeec;">Plug in your device to start AndroidAuto (tm).</span></p></body></html></string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
<widget class="QLabel" name="labelProjectHomePage">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>10</x>
|
|
||||||
<y>440</y>
|
|
||||||
<width>271</width>
|
|
||||||
<height>31</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string><html><head/><body><p><a href="https://github.com/f1xpl/openauto"><span style=" text-decoration: underline; color:#007af4;">https://github.com/f1xpl/openauto</span></a></p></body></html></string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
<widget class="QLabel" name="labelDistractionWarningIcon">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>30</x>
|
|
||||||
<y>170</y>
|
|
||||||
<width>31</width>
|
|
||||||
<height>41</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string><html><head/><body><p><img src=":/ico_warning.png"/></p></body></html></string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
<widget class="QLabel" name="labelDistractionWarning">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>80</x>
|
|
||||||
<y>130</y>
|
|
||||||
<width>531</width>
|
|
||||||
<height>101</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string><html><head/><body><p align="center"><span style=" color:#ef2929;">WARNING!</span></p><p><span style=" color:#ef2929;">Distraction may cause accidents. Do not attempt to operate while driving. Always concentrate on driving and obey Traffic Regulations. You assume total responsibility and risk for using this software.</span></p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="wordWrap">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
<widget class="QLabel" name="labelCertificationWarning">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>80</x>
|
|
||||||
<y>240</y>
|
|
||||||
<width>531</width>
|
|
||||||
<height>121</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string><html><head/><body><p><span style=" color:#ef2929;">This software is not certified by Google Inc. It is created for R&amp;D purposes and may not work as expected by the original authors. Do not use while driving.</span></p><p><span style=" color:#ef2929;">You use this software at your own risk.</span></p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="wordWrap">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
<widget class="QLabel" name="labelCertificationWarningIcon">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>30</x>
|
|
||||||
<y>270</y>
|
|
||||||
<width>31</width>
|
|
||||||
<height>41</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string><html><head/><body><p><img src=":/ico_warning.png"/></p></body></html></string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
<widget class="QLabel" name="labelCopyrightsInfoIcon">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>410</x>
|
|
||||||
<y>440</y>
|
|
||||||
<width>21</width>
|
|
||||||
<height>31</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string><html><head/><body><p><img src=":/ico_info.png"/></p></body></html></string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
<widget class="QLabel" name="labelTrademark">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>440</x>
|
|
||||||
<y>440</y>
|
|
||||||
<width>351</width>
|
|
||||||
<height>31</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string><html><head/><body><p><span style=" font-style:italic;">AndroidAuto is registered trademark of Google Inc.</span></p></body></html></string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
<widget class="QPushButton" name="pushButtonToggleCursor">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>630</x>
|
|
||||||
<y>230</y>
|
|
||||||
<width>161</width>
|
|
||||||
<height>41</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Toggle cursor</string>
|
|
||||||
</property>
|
|
||||||
<property name="autoDefault">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="default">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
<widget class="QPushButton" name="pushButtonWirelessConnection">
|
<widget class="QPushButton" name="pushButtonWirelessConnection">
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>630</x>
|
|
||||||
<y>280</y>
|
|
||||||
<width>161</width>
|
|
||||||
<height>41</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Wireless connection</string>
|
<string>Wireless connection</string>
|
||||||
</property>
|
</property>
|
||||||
@ -227,22 +471,24 @@ color: rgb(238, 238, 236);</string>
|
|||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QLabel" name="label_2">
|
</item>
|
||||||
<property name="geometry">
|
<item>
|
||||||
<rect>
|
<widget class="QPushButton" name="pushButtonToggleCursor">
|
||||||
<x>50</x>
|
|
||||||
<y>370</y>
|
|
||||||
<width>551</width>
|
|
||||||
<height>61</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string><html><head/><body><p align="center"><span style=" font-weight:600;">If you are looking for a Raspberry PI compatible 12V power supply equipped with an ignition switch, visit </span><a href="https://bluewavestudio.io/"><span style=" text-decoration: underline; color:#007af4;">https://bluewavestudio.io</span></a></p></body></html></string>
|
<string>Toggle cursor</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="wordWrap">
|
<property name="autoDefault">
|
||||||
<bool>true</bool>
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="default">
|
||||||
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
@ -251,6 +497,8 @@ color: rgb(238, 238, 236);</string>
|
|||||||
<tabstop>pushButtonSettings</tabstop>
|
<tabstop>pushButtonSettings</tabstop>
|
||||||
<tabstop>pushButtonExit</tabstop>
|
<tabstop>pushButtonExit</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
<resources/>
|
<resources>
|
||||||
|
<include location="../assets/resources.qrc"/>
|
||||||
|
</resources>
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
||||||
|
BIN
autoapp/assets/album.png
Normal file
BIN
autoapp/assets/album.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 896 B |
BIN
autoapp/assets/artist.png
Normal file
BIN
autoapp/assets/artist.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 935 B |
BIN
autoapp/assets/bluetooth.png
Normal file
BIN
autoapp/assets/bluetooth.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 931 B |
BIN
autoapp/assets/radio.png
Normal file
BIN
autoapp/assets/radio.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 816 B |
@ -1,5 +1,10 @@
|
|||||||
<RCC>
|
<RCC>
|
||||||
<qresource prefix="/">
|
<qresource prefix="/">
|
||||||
|
<file>radio.png</file>
|
||||||
|
<file>album.png</file>
|
||||||
|
<file>artist.png</file>
|
||||||
|
<file>bluetooth.png</file>
|
||||||
|
<file>song.png</file>
|
||||||
<file>ico_androidauto.png</file>
|
<file>ico_androidauto.png</file>
|
||||||
<file>ico_warning.png</file>
|
<file>ico_warning.png</file>
|
||||||
<file>ico_setting.png</file>
|
<file>ico_setting.png</file>
|
||||||
|
BIN
autoapp/assets/song.png
Normal file
BIN
autoapp/assets/song.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 821 B |
@ -43,20 +43,33 @@ btservice::btservice(openauto::configuration::IConfiguration::Pointer config)
|
|||||||
|
|
||||||
void btservice::connectToBluetooth(QBluetoothAddress addr, QBluetoothAddress controller)
|
void btservice::connectToBluetooth(QBluetoothAddress addr, QBluetoothAddress controller)
|
||||||
{
|
{
|
||||||
|
// Update 07-12-22, with bluez update and krnbt, raspberry pi is behaving as expected. For this reason
|
||||||
|
// the RPI specific code has been commented out. The commented out code (and comments below this one)
|
||||||
|
// exist as legacy now - in case there's a scenario where someone cannot update to krnbt or newer bluez.
|
||||||
|
|
||||||
|
|
||||||
// The raspberry pi has a really tough time using bluetoothctl (or really anything) to connect to an Android phone
|
// The raspberry pi has a really tough time using bluetoothctl (or really anything) to connect to an Android phone
|
||||||
// even though phone connecting to the pi is fine.
|
// even though phone connecting to the pi is fine.
|
||||||
// I found a workaround where you can make the pi attempt an rfcomm connection to the phone, and it connects immediately
|
// I found a workaround where you can make the pi attempt an rfcomm connection to the phone, and it connects immediately
|
||||||
// This might require setting u+s on rfcomm though
|
// This might require setting u+s on rfcomm though
|
||||||
// Other computers with more sane bluetooth shouldn't have an issue using bluetoothctl
|
// Other computers with more sane bluetooth shouldn't have an issue using bluetoothctl
|
||||||
|
|
||||||
|
// Update 01-10-21, latest firmware/package updates seem to have made bluetoothctl more stable
|
||||||
|
// and it won't drop a connection anymore. Only issue, is that the connection will fail
|
||||||
|
// if the desired target hasn't been "seen" yet
|
||||||
|
// we can use hcitool to force the pi to recognize that we're trying to connect to a valid device.
|
||||||
|
// this causes the target device to be "seen"
|
||||||
|
// bluetoothctl can then connect as normal.
|
||||||
|
// Why don't we just use rfcomm (as we had previously on pis)? Because an rfcomm initiated connection doesn't connect HFP, which breaks the use of
|
||||||
|
// pi mic/speakers for android auto phone calls. bluetoothctl will connect all profiles.
|
||||||
|
|
||||||
#ifdef RPI
|
#ifdef RPI
|
||||||
// tries to open an rfcomm serial on channel 2
|
// QString program = QString::fromStdString("sudo hcitool cc ")+addr.toString();
|
||||||
// channel doesn't really matter here, 2 is just "somewhat standard"
|
// btConnectProcess = new QProcess();
|
||||||
QString program = QString::fromStdString("sudo stdbuf -oL rfcomm connect hci0 ")+addr.toString()+QString::fromStdString(" 2");
|
// OPENAUTO_LOG(info)<<"[btservice] Attempting to connect to last bluetooth device, "<<addr.toString().toStdString()<<" using hcitool/bluetoothctl hybrid";
|
||||||
btConnectProcess = new QProcess();
|
// btConnectProcess->start(program, QProcess::Unbuffered | QProcess::ReadWrite);
|
||||||
OPENAUTO_LOG(info)<<"[btservice] Attempting to connect to last bluetooth device, "<<addr.toString().toStdString()<<" with `"<<program.toStdString();
|
// btConnectProcess->waitForFinished();
|
||||||
btConnectProcess->start(program, QProcess::Unbuffered | QProcess::ReadWrite);
|
#endif
|
||||||
#else
|
|
||||||
btConnectProcess = new QProcess();
|
btConnectProcess = new QProcess();
|
||||||
btConnectProcess->setProcessChannelMode(QProcess::SeparateChannels);
|
btConnectProcess->setProcessChannelMode(QProcess::SeparateChannels);
|
||||||
OPENAUTO_LOG(info)<<"[btservice] Attempting to connect to last bluetooth device, "<<addr.toString().toStdString()<<" with bluetoothctl";
|
OPENAUTO_LOG(info)<<"[btservice] Attempting to connect to last bluetooth device, "<<addr.toString().toStdString()<<" with bluetoothctl";
|
||||||
@ -66,9 +79,6 @@ void btservice::connectToBluetooth(QBluetoothAddress addr, QBluetoothAddress con
|
|||||||
btConnectProcess->write(QString("connect %1\n").arg(addr.toString()).toUtf8());
|
btConnectProcess->write(QString("connect %1\n").arg(addr.toString()).toUtf8());
|
||||||
btConnectProcess->closeWriteChannel();
|
btConnectProcess->closeWriteChannel();
|
||||||
btConnectProcess->waitForFinished();
|
btConnectProcess->waitForFinished();
|
||||||
#endif
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
26
cmake_modules/Findh264.cmake
Normal file
26
cmake_modules/Findh264.cmake
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
set (H264_INCLUDE_DIR /usr/local/include/h264bitstream)
|
||||||
|
set (H264_LIB_DIR /usr/local/lib)
|
||||||
|
|
||||||
|
set(H264_FOUND TRUE)
|
||||||
|
|
||||||
|
if (H264_FOUND)
|
||||||
|
if (NOT h264_FIND_QUIETLY)
|
||||||
|
message(STATUS "Found h264bitstream:")
|
||||||
|
message(STATUS " - Includes: ${H264_INCLUDE_DIR}")
|
||||||
|
message(STATUS " - Libraries: ${H264_LIB_DIR}")
|
||||||
|
endif()
|
||||||
|
add_library(h264 INTERFACE)
|
||||||
|
target_include_directories(h264 INTERFACE ${H264_INCLUDE_DIR})
|
||||||
|
set_target_properties(h264 PROPERTIES INTERFACE_LINK_DIRECTORIES ${H264_LIB_DIR})
|
||||||
|
target_link_libraries(h264 INTERFACE libh264bitstream.so)
|
||||||
|
else()
|
||||||
|
if (h264_FIND_REQUIRED)
|
||||||
|
if(H264_INCLUDE_DIR)
|
||||||
|
message(FATAL_ERROR "h264 was found but not built. Perform an in-source build.")
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "Could not find h264")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
mark_as_advanced(H264_INCLUDE_DIR H264_LIBRARIES)
|
51
cmake_modules/gitversion.cmake
Normal file
51
cmake_modules/gitversion.cmake
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# cmake/gitversion.cmake
|
||||||
|
cmake_minimum_required(VERSION 3.0.0)
|
||||||
|
|
||||||
|
message(STATUS "Resolving GIT Version")
|
||||||
|
|
||||||
|
set(_build_version "unknown")
|
||||||
|
set(_commit_timestamp "unknown")
|
||||||
|
|
||||||
|
find_package(Git)
|
||||||
|
if(GIT_FOUND)
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD
|
||||||
|
WORKING_DIRECTORY "${local_dir}"
|
||||||
|
OUTPUT_VARIABLE _build_version
|
||||||
|
ERROR_QUIET
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD
|
||||||
|
WORKING_DIRECTORY "${local_dir}"
|
||||||
|
OUTPUT_VARIABLE _build_branch
|
||||||
|
ERROR_QUIET
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${GIT_EXECUTABLE} log -1 --format=%at
|
||||||
|
WORKING_DIRECTORY "${local_dir}"
|
||||||
|
OUTPUT_VARIABLE _commit_timestamp
|
||||||
|
ERROR_QUIET
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
message( STATUS "GIT hash: ${_build_version}; branch: ${_build_branch}; Commit epoch: ${_commit_timestamp};")
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${GIT_EXECUTABLE} diff --no-ext-diff --quiet
|
||||||
|
WORKING_DIRECTORY "${local_dir}"
|
||||||
|
RESULT_VARIABLE ret
|
||||||
|
)
|
||||||
|
if(ret EQUAL "1")
|
||||||
|
set(_build_changes "*")
|
||||||
|
else()
|
||||||
|
set(_build_changes "")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
else()
|
||||||
|
message(STATUS "GIT not found")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# branch name
|
||||||
|
# git rev-parse --abbrev-ref HEAD
|
||||||
|
# changed
|
||||||
|
# git diff --no-ext-diff --quiet
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
|
#include <QtWebSockets/QWebSocket>
|
||||||
|
|
||||||
namespace Ui
|
namespace Ui
|
||||||
{
|
{
|
||||||
@ -44,8 +45,16 @@ signals:
|
|||||||
void toggleCursor();
|
void toggleCursor();
|
||||||
void openConnectDialog();
|
void openConnectDialog();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void connectWebSocket();
|
||||||
|
void handleIncomingMessage(const QString &message);
|
||||||
|
void updateBtNowPlaying();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::MainWindow *ui_;
|
Ui::MainWindow *ui_;
|
||||||
|
QWebSocket *webSocket;
|
||||||
|
QTimer *reconnectTimer;
|
||||||
|
bool shuttingDown;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,8 @@ public:
|
|||||||
int32_t getOMXLayerIndex() const override;
|
int32_t getOMXLayerIndex() const override;
|
||||||
void setVideoMargins(QRect value) override;
|
void setVideoMargins(QRect value) override;
|
||||||
QRect getVideoMargins() const override;
|
QRect getVideoMargins() const override;
|
||||||
|
void setWhitescreenWorkaround(bool value) override;
|
||||||
|
bool getWhitescreenWorkaround() const override;
|
||||||
|
|
||||||
bool getTouchscreenEnabled() const override;
|
bool getTouchscreenEnabled() const override;
|
||||||
void setTouchscreenEnabled(bool value) override;
|
void setTouchscreenEnabled(bool value) override;
|
||||||
@ -91,6 +93,7 @@ private:
|
|||||||
size_t screenDPI_;
|
size_t screenDPI_;
|
||||||
int32_t omxLayerIndex_;
|
int32_t omxLayerIndex_;
|
||||||
QRect videoMargins_;
|
QRect videoMargins_;
|
||||||
|
bool whitescreenWorkaround_;
|
||||||
bool enableTouchscreen_;
|
bool enableTouchscreen_;
|
||||||
ButtonCodes buttonCodes_;
|
ButtonCodes buttonCodes_;
|
||||||
BluetoothAdapterType bluetoothAdapterType_;
|
BluetoothAdapterType bluetoothAdapterType_;
|
||||||
@ -115,6 +118,7 @@ private:
|
|||||||
static const std::string cVideoOMXLayerIndexKey;
|
static const std::string cVideoOMXLayerIndexKey;
|
||||||
static const std::string cVideoMarginWidth;
|
static const std::string cVideoMarginWidth;
|
||||||
static const std::string cVideoMarginHeight;
|
static const std::string cVideoMarginHeight;
|
||||||
|
static const std::string cVideoWhitescreenWorkaround;
|
||||||
|
|
||||||
static const std::string cAudioMusicAudioChannelEnabled;
|
static const std::string cAudioMusicAudioChannelEnabled;
|
||||||
static const std::string cAudioSpeechAudioChannelEnabled;
|
static const std::string cAudioSpeechAudioChannelEnabled;
|
||||||
|
@ -59,6 +59,8 @@ public:
|
|||||||
virtual int32_t getOMXLayerIndex() const = 0;
|
virtual int32_t getOMXLayerIndex() const = 0;
|
||||||
virtual void setVideoMargins(QRect value) = 0;
|
virtual void setVideoMargins(QRect value) = 0;
|
||||||
virtual QRect getVideoMargins() const = 0;
|
virtual QRect getVideoMargins() const = 0;
|
||||||
|
virtual void setWhitescreenWorkaround(bool value) = 0;
|
||||||
|
virtual bool getWhitescreenWorkaround() const = 0;
|
||||||
|
|
||||||
virtual bool getTouchscreenEnabled() const = 0;
|
virtual bool getTouchscreenEnabled() const = 0;
|
||||||
virtual void setTouchscreenEnabled(bool value) = 0;
|
virtual void setTouchscreenEnabled(bool value) = 0;
|
||||||
|
@ -51,6 +51,46 @@ namespace openauto
|
|||||||
namespace projection
|
namespace projection
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// enum of possible h264 decoders dash will attempt to use
|
||||||
|
enum H264_Decoder {
|
||||||
|
nvcodec,
|
||||||
|
v4l2,
|
||||||
|
omx,
|
||||||
|
vaapi,
|
||||||
|
libav,
|
||||||
|
unknown
|
||||||
|
};
|
||||||
|
|
||||||
|
// order of priority for decoders - dash will use the first decoder it can find in this list
|
||||||
|
// for sake of the code, don't include "unknown" as a decoder to search for - this is the default case.
|
||||||
|
const H264_Decoder H264_Decoder_Priority_List[] = { nvcodec, v4l2, omx, libav };
|
||||||
|
|
||||||
|
// A map of enum to actual pad name we want to use
|
||||||
|
inline const char* ToString(H264_Decoder v)
|
||||||
|
{
|
||||||
|
switch (v)
|
||||||
|
{
|
||||||
|
case nvcodec: return "nvh264dec";
|
||||||
|
case v4l2: return "v4l2h264dec";
|
||||||
|
case omx: return "omxh264dec";
|
||||||
|
case libav: return "avdec_h264";
|
||||||
|
default: return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// A map of enum to pipeline steps to insert (because for some we need some video converting)
|
||||||
|
inline const char* ToPipeline(H264_Decoder v)
|
||||||
|
{
|
||||||
|
switch (v)
|
||||||
|
{
|
||||||
|
// we're going to assume that any machine with an nvidia card has a cpu powerful enough for video convert.
|
||||||
|
case nvcodec: return "nvh264dec ! videoconvert";
|
||||||
|
case v4l2: return "v4l2h264dec";
|
||||||
|
case omx: return "omxh264dec";
|
||||||
|
case libav: return "avdec_h264";
|
||||||
|
default: return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class GSTVideoOutput: public QObject, public VideoOutput, boost::noncopyable
|
class GSTVideoOutput: public QObject, public VideoOutput, boost::noncopyable
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -72,13 +112,19 @@ protected slots:
|
|||||||
void onStartPlayback();
|
void onStartPlayback();
|
||||||
void onStopPlayback();
|
void onStopPlayback();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void dumpDot();
|
||||||
private:
|
private:
|
||||||
static GstPadProbeReturn convertProbe(GstPad* pad, GstPadProbeInfo* info, void*);
|
static GstPadProbeReturn convertProbe(GstPad* pad, GstPadProbeInfo* info, void*);
|
||||||
static gboolean busCallback(GstBus*, GstMessage* message, gpointer*);
|
static gboolean busCallback(GstBus*, GstMessage* message, gpointer*);
|
||||||
|
H264_Decoder findPreferredVideoDecoder();
|
||||||
|
|
||||||
|
bool firstHeaderParsed = false;
|
||||||
|
|
||||||
QGst::ElementPtr videoSink_;
|
QGst::ElementPtr videoSink_;
|
||||||
QQuickWidget* videoWidget_;
|
QQuickWidget* videoWidget_;
|
||||||
GstElement* vidPipeline_;
|
GstElement* vidPipeline_;
|
||||||
|
GstVideoFilter* vidCrop_;
|
||||||
GstAppSrc* vidSrc_;
|
GstAppSrc* vidSrc_;
|
||||||
QWidget* videoContainer_;
|
QWidget* videoContainer_;
|
||||||
QGst::Quick::VideoSurface* surface_;
|
QGst::Quick::VideoSurface* surface_;
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "InputEvent.hpp"
|
#include "InputEvent.hpp"
|
||||||
|
#include "aasdk_proto/InputEventIndicationMessage.pb.h"
|
||||||
|
|
||||||
|
|
||||||
namespace openauto
|
namespace openauto
|
||||||
{
|
{
|
||||||
@ -31,7 +33,9 @@ public:
|
|||||||
virtual ~IInputDeviceEventHandler() = default;
|
virtual ~IInputDeviceEventHandler() = default;
|
||||||
|
|
||||||
virtual void onButtonEvent(const ButtonEvent& event) = 0;
|
virtual void onButtonEvent(const ButtonEvent& event) = 0;
|
||||||
virtual void onTouchEvent(const TouchEvent& event) = 0;
|
virtual void onTouchEvent(aasdk::proto::messages::InputEventIndication inputEventIndication) = 0;
|
||||||
|
virtual void onMouseEvent(const projection::TouchEvent& event) = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
#include "IInputDevice.hpp"
|
#include "IInputDevice.hpp"
|
||||||
#include "openauto/Configuration/IConfiguration.hpp"
|
#include "openauto/Configuration/IConfiguration.hpp"
|
||||||
|
#include <bits/stdc++.h>
|
||||||
|
|
||||||
namespace openauto
|
namespace openauto
|
||||||
{
|
{
|
||||||
@ -48,6 +49,7 @@ private:
|
|||||||
bool handleKeyEvent(QEvent* event, QKeyEvent* key);
|
bool handleKeyEvent(QEvent* event, QKeyEvent* key);
|
||||||
void dispatchKeyEvent(ButtonEvent event);
|
void dispatchKeyEvent(ButtonEvent event);
|
||||||
bool handleTouchEvent(QEvent* event);
|
bool handleTouchEvent(QEvent* event);
|
||||||
|
bool handleMouseEvent(QEvent* event);
|
||||||
|
|
||||||
QObject& parent_;
|
QObject& parent_;
|
||||||
configuration::IConfiguration::Pointer configuration_;
|
configuration::IConfiguration::Pointer configuration_;
|
||||||
@ -55,6 +57,10 @@ private:
|
|||||||
QRect displayGeometry_;
|
QRect displayGeometry_;
|
||||||
IInputDeviceEventHandler* eventHandler_;
|
IInputDeviceEventHandler* eventHandler_;
|
||||||
std::mutex mutex_;
|
std::mutex mutex_;
|
||||||
|
|
||||||
|
std::priority_queue <int, std::vector<int>, std::greater<int> > pointer_id_queue;
|
||||||
|
QMap<int, int> pointer_map;
|
||||||
|
int max_pointers = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ private:
|
|||||||
uint32_t sampleRate_;
|
uint32_t sampleRate_;
|
||||||
SequentialBuffer audioBuffer_;
|
SequentialBuffer audioBuffer_;
|
||||||
std::unique_ptr<RtAudio> dac_;
|
std::unique_ptr<RtAudio> dac_;
|
||||||
std::mutex mutex_;
|
static std::mutex mutex_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
88
include/openauto/Service/IAndroidAutoInterface.hpp
Normal file
88
include/openauto/Service/IAndroidAutoInterface.hpp
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of openauto project.
|
||||||
|
* Copyright (C) 2018 f1x.studio (Michal Szwaj)
|
||||||
|
*
|
||||||
|
* openauto is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
|
||||||
|
* openauto is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with openauto. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "aasdk_proto/ButtonCodeEnum.pb.h"
|
||||||
|
#include "openauto/Projection/InputEvent.hpp"
|
||||||
|
#include "aasdk_proto/MediaInfoChannelMetadataData.pb.h"
|
||||||
|
#include "aasdk_proto/MediaInfoChannelPlaybackData.pb.h"
|
||||||
|
#include "aasdk_proto/NavigationStatusMessage.pb.h"
|
||||||
|
#include "aasdk_proto/NavigationDistanceEventMessage.pb.h"
|
||||||
|
#include "aasdk_proto/NavigationTurnEventMessage.pb.h"
|
||||||
|
#include "openauto/Service/ServiceFactory.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace openauto
|
||||||
|
{
|
||||||
|
namespace service
|
||||||
|
{
|
||||||
|
|
||||||
|
class IAndroidAutoInterface: public std::enable_shared_from_this<IAndroidAutoInterface>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::shared_ptr<IAndroidAutoInterface> getPtr()
|
||||||
|
{
|
||||||
|
return shared_from_this();
|
||||||
|
}
|
||||||
|
typedef std::shared_ptr<IAndroidAutoInterface> Pointer;
|
||||||
|
|
||||||
|
virtual ~IAndroidAutoInterface() = default;
|
||||||
|
|
||||||
|
virtual void mediaPlaybackUpdate(const aasdk::proto::messages::MediaInfoChannelPlaybackData& playback) = 0;
|
||||||
|
virtual void mediaMetadataUpdate(const aasdk::proto::messages::MediaInfoChannelMetadataData& metadata) = 0;
|
||||||
|
virtual void navigationStatusUpdate(const aasdk::proto::messages::NavigationStatus& navStatus) = 0;
|
||||||
|
virtual void navigationTurnEvent(const aasdk::proto::messages::NavigationTurnEvent& turnEvent) = 0;
|
||||||
|
virtual void navigationDistanceEvent(const aasdk::proto::messages::NavigationDistanceEvent& distanceEvent) = 0;
|
||||||
|
void setServiceFactory(ServiceFactory* serviceFactory)
|
||||||
|
{
|
||||||
|
this->m_serviceFactory = serviceFactory;
|
||||||
|
|
||||||
|
}
|
||||||
|
void injectButtonPress(aasdk::proto::enums::ButtonCode::Enum buttonCode, projection::WheelDirection wheelDirection=openauto::projection::WheelDirection::NONE, projection::ButtonEventType buttonEventType = projection::ButtonEventType::NONE)
|
||||||
|
{
|
||||||
|
if(m_serviceFactory != NULL)
|
||||||
|
{
|
||||||
|
|
||||||
|
m_serviceFactory->sendButtonPress(buttonCode, wheelDirection, buttonEventType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void injectButtonPress(aasdk::proto::enums::ButtonCode::Enum buttonCode, projection::ButtonEventType buttonEventType)
|
||||||
|
{
|
||||||
|
this->injectButtonPress(buttonCode, projection::WheelDirection::NONE, buttonEventType);
|
||||||
|
}
|
||||||
|
void setNightMode(bool mode)
|
||||||
|
{
|
||||||
|
if(m_serviceFactory != NULL)
|
||||||
|
{
|
||||||
|
|
||||||
|
m_serviceFactory->setNightMode(mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
using std::enable_shared_from_this<IAndroidAutoInterface>::shared_from_this;
|
||||||
|
ServiceFactory* m_serviceFactory;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -38,6 +38,7 @@ class InputService:
|
|||||||
public:
|
public:
|
||||||
InputService(boost::asio::io_service& ioService, aasdk::messenger::IMessenger::Pointer messenger, projection::IInputDevice::Pointer inputDevice);
|
InputService(boost::asio::io_service& ioService, aasdk::messenger::IMessenger::Pointer messenger, projection::IInputDevice::Pointer inputDevice);
|
||||||
|
|
||||||
|
void sendButtonPress(aasdk::proto::enums::ButtonCode::Enum buttonCode, projection::WheelDirection wheelDirection = projection::WheelDirection::NONE, projection::ButtonEventType buttonEventType = projection::ButtonEventType::NONE);
|
||||||
void start() override;
|
void start() override;
|
||||||
void stop() override;
|
void stop() override;
|
||||||
void fillFeatures(aasdk::proto::messages::ServiceDiscoveryResponse& response) override;
|
void fillFeatures(aasdk::proto::messages::ServiceDiscoveryResponse& response) override;
|
||||||
@ -45,7 +46,8 @@ public:
|
|||||||
void onBindingRequest(const aasdk::proto::messages::BindingRequest& request) override;
|
void onBindingRequest(const aasdk::proto::messages::BindingRequest& request) override;
|
||||||
void onChannelError(const aasdk::error::Error& e) override;
|
void onChannelError(const aasdk::error::Error& e) override;
|
||||||
void onButtonEvent(const projection::ButtonEvent& event) override;
|
void onButtonEvent(const projection::ButtonEvent& event) override;
|
||||||
void onTouchEvent(const projection::TouchEvent& event) override;
|
void onTouchEvent(aasdk::proto::messages::InputEventIndication inputEventIndication) override;
|
||||||
|
void onMouseEvent(const projection::TouchEvent& event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using std::enable_shared_from_this<InputService>::shared_from_this;
|
using std::enable_shared_from_this<InputService>::shared_from_this;
|
||||||
@ -53,6 +55,7 @@ private:
|
|||||||
boost::asio::io_service::strand strand_;
|
boost::asio::io_service::strand strand_;
|
||||||
aasdk::channel::input::InputServiceChannel::Pointer channel_;
|
aasdk::channel::input::InputServiceChannel::Pointer channel_;
|
||||||
projection::IInputDevice::Pointer inputDevice_;
|
projection::IInputDevice::Pointer inputDevice_;
|
||||||
|
bool serviceActive = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
52
include/openauto/Service/MediaStatusService.hpp
Normal file
52
include/openauto/Service/MediaStatusService.hpp
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of openauto project.
|
||||||
|
* Copyright (C) 2018 f1x.studio (Michal Szwaj)
|
||||||
|
*
|
||||||
|
* openauto is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
|
||||||
|
* openauto is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with openauto. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "aasdk/Channel/AV/MediaStatusServiceChannel.hpp"
|
||||||
|
#include "IService.hpp"
|
||||||
|
|
||||||
|
namespace openauto
|
||||||
|
{
|
||||||
|
namespace service
|
||||||
|
{
|
||||||
|
class IAndroidAutoInterface;
|
||||||
|
class MediaStatusService: public aasdk::channel::av::IMediaStatusServiceChannelEventHandler, public IService, public std::enable_shared_from_this<MediaStatusService>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MediaStatusService(boost::asio::io_service& ioService, aasdk::messenger::IMessenger::Pointer messenger, IAndroidAutoInterface* aa_interface);
|
||||||
|
void start() override;
|
||||||
|
void stop() override;
|
||||||
|
void fillFeatures(aasdk::proto::messages::ServiceDiscoveryResponse& response) override;
|
||||||
|
void onChannelOpenRequest(const aasdk::proto::messages::ChannelOpenRequest& request) override;
|
||||||
|
void onChannelError(const aasdk::error::Error& e) override;
|
||||||
|
void onMetadataUpdate(const aasdk::proto::messages::MediaInfoChannelMetadataData& metadata) override;
|
||||||
|
void onPlaybackUpdate(const aasdk::proto::messages::MediaInfoChannelPlaybackData& playback) override;
|
||||||
|
void setAndroidAutoInterface(IAndroidAutoInterface* aa_interface);
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
using std::enable_shared_from_this<MediaStatusService>::shared_from_this;
|
||||||
|
|
||||||
|
boost::asio::io_service::strand strand_;
|
||||||
|
aasdk::channel::av::MediaStatusServiceChannel::Pointer channel_;
|
||||||
|
IAndroidAutoInterface* aa_interface_ = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
54
include/openauto/Service/NavigationStatusService.hpp
Normal file
54
include/openauto/Service/NavigationStatusService.hpp
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of openauto project.
|
||||||
|
* Copyright (C) 2018 f1x.studio (Michal Szwaj)
|
||||||
|
*
|
||||||
|
* openauto is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
|
||||||
|
* openauto is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with openauto. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "aasdk/Channel/Navigation/NavigationStatusServiceChannel.hpp"
|
||||||
|
#include "IService.hpp"
|
||||||
|
|
||||||
|
namespace openauto
|
||||||
|
{
|
||||||
|
namespace service
|
||||||
|
{
|
||||||
|
class IAndroidAutoInterface;
|
||||||
|
class NavigationStatusService: public aasdk::channel::navigation::INavigationStatusServiceChannelEventHandler, public IService, public std::enable_shared_from_this<NavigationStatusService>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NavigationStatusService(boost::asio::io_service& ioService, aasdk::messenger::IMessenger::Pointer messenger, IAndroidAutoInterface* aa_interface);
|
||||||
|
void start() override;
|
||||||
|
void stop() override;
|
||||||
|
void fillFeatures(aasdk::proto::messages::ServiceDiscoveryResponse& response) override;
|
||||||
|
void onChannelOpenRequest(const aasdk::proto::messages::ChannelOpenRequest& request) override;
|
||||||
|
void onChannelError(const aasdk::error::Error& e) override;
|
||||||
|
void onTurnEvent(const aasdk::proto::messages::NavigationTurnEvent& turnEvent) override;
|
||||||
|
void onDistanceEvent(const aasdk::proto::messages::NavigationDistanceEvent& distanceEvent) override;
|
||||||
|
void onStatusUpdate(const aasdk::proto::messages::NavigationStatus& navStatus) override;
|
||||||
|
void setAndroidAutoInterface(IAndroidAutoInterface* aa_interface);
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
using std::enable_shared_from_this<NavigationStatusService>::shared_from_this;
|
||||||
|
|
||||||
|
boost::asio::io_service::strand strand_;
|
||||||
|
aasdk::channel::navigation::NavigationStatusServiceChannel::Pointer channel_;
|
||||||
|
IAndroidAutoInterface* aa_interface_ = nullptr;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -24,14 +24,17 @@
|
|||||||
#include "openauto/Projection/OMXVideoOutput.hpp"
|
#include "openauto/Projection/OMXVideoOutput.hpp"
|
||||||
#include "openauto/Projection/GSTVideoOutput.hpp"
|
#include "openauto/Projection/GSTVideoOutput.hpp"
|
||||||
#include "openauto/Projection/QtVideoOutput.hpp"
|
#include "openauto/Projection/QtVideoOutput.hpp"
|
||||||
|
#include "openauto/Service/MediaStatusService.hpp"
|
||||||
|
#include "openauto/Service/NavigationStatusService.hpp"
|
||||||
#include "openauto/Service/SensorService.hpp"
|
#include "openauto/Service/SensorService.hpp"
|
||||||
|
#include "openauto/Service/InputService.hpp"
|
||||||
#include "btservice/btservice.hpp"
|
#include "btservice/btservice.hpp"
|
||||||
|
|
||||||
namespace openauto
|
namespace openauto
|
||||||
{
|
{
|
||||||
namespace service
|
namespace service
|
||||||
{
|
{
|
||||||
|
class IAndroidAutoInterface;
|
||||||
class ServiceFactory : public IServiceFactory
|
class ServiceFactory : public IServiceFactory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -40,7 +43,9 @@ public:
|
|||||||
void setOpacity(unsigned int alpha);
|
void setOpacity(unsigned int alpha);
|
||||||
void resize();
|
void resize();
|
||||||
void setNightMode(bool nightMode);
|
void setNightMode(bool nightMode);
|
||||||
|
void sendButtonPress(aasdk::proto::enums::ButtonCode::Enum buttonCode, projection::WheelDirection wheelDirection = projection::WheelDirection::NONE, projection::ButtonEventType buttonEventType = projection::ButtonEventType::NONE);
|
||||||
void sendKeyEvent(QKeyEvent* event);
|
void sendKeyEvent(QKeyEvent* event);
|
||||||
|
void setAndroidAutoInterface(IAndroidAutoInterface* aa_interface);
|
||||||
static QRect mapActiveAreaToGlobal(QWidget* activeArea);
|
static QRect mapActiveAreaToGlobal(QWidget* activeArea);
|
||||||
#ifdef USE_OMX
|
#ifdef USE_OMX
|
||||||
static projection::DestRect QRectToDestRect(QRect rect);
|
static projection::DestRect QRectToDestRect(QRect rect);
|
||||||
@ -49,7 +54,9 @@ public:
|
|||||||
private:
|
private:
|
||||||
IService::Pointer createVideoService(aasdk::messenger::IMessenger::Pointer messenger);
|
IService::Pointer createVideoService(aasdk::messenger::IMessenger::Pointer messenger);
|
||||||
IService::Pointer createBluetoothService(aasdk::messenger::IMessenger::Pointer messenger);
|
IService::Pointer createBluetoothService(aasdk::messenger::IMessenger::Pointer messenger);
|
||||||
IService::Pointer createInputService(aasdk::messenger::IMessenger::Pointer messenger);
|
std::shared_ptr<NavigationStatusService> createNavigationStatusService(aasdk::messenger::IMessenger::Pointer messenger);
|
||||||
|
std::shared_ptr<MediaStatusService> createMediaStatusService(aasdk::messenger::IMessenger::Pointer messenger);
|
||||||
|
std::shared_ptr<InputService> createInputService(aasdk::messenger::IMessenger::Pointer messenger);
|
||||||
void createAudioServices(ServiceList& serviceList, aasdk::messenger::IMessenger::Pointer messenger);
|
void createAudioServices(ServiceList& serviceList, aasdk::messenger::IMessenger::Pointer messenger);
|
||||||
|
|
||||||
boost::asio::io_service& ioService_;
|
boost::asio::io_service& ioService_;
|
||||||
@ -68,6 +75,10 @@ private:
|
|||||||
btservice::btservice btservice_;
|
btservice::btservice btservice_;
|
||||||
bool nightMode_;
|
bool nightMode_;
|
||||||
std::weak_ptr<SensorService> sensorService_;
|
std::weak_ptr<SensorService> sensorService_;
|
||||||
|
std::weak_ptr<InputService> inputService_;
|
||||||
|
std::weak_ptr<MediaStatusService> mediaStatusService_;
|
||||||
|
std::weak_ptr<NavigationStatusService> navStatusService_;
|
||||||
|
IAndroidAutoInterface* aa_interface_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,8 @@ add_library(openauto SHARED
|
|||||||
Service/Pinger.cpp
|
Service/Pinger.cpp
|
||||||
Service/AndroidAutoEntity.cpp
|
Service/AndroidAutoEntity.cpp
|
||||||
Service/VideoService.cpp
|
Service/VideoService.cpp
|
||||||
|
Service/NavigationStatusService.cpp
|
||||||
|
Service/MediaStatusService.cpp
|
||||||
Configuration/RecentAddressesList.cpp
|
Configuration/RecentAddressesList.cpp
|
||||||
Configuration/Configuration.cpp
|
Configuration/Configuration.cpp
|
||||||
Projection/RemoteBluetoothDevice.cpp
|
Projection/RemoteBluetoothDevice.cpp
|
||||||
@ -28,6 +30,7 @@ add_library(openauto SHARED
|
|||||||
Projection/RtAudioOutput.cpp
|
Projection/RtAudioOutput.cpp
|
||||||
Projection/QtAudioOutput.cpp
|
Projection/QtAudioOutput.cpp
|
||||||
${CMAKE_SOURCE_DIR}/btservice/AndroidBluetoothServer.cpp
|
${CMAKE_SOURCE_DIR}/btservice/AndroidBluetoothServer.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/btservice/AndroidBluetoothServer.cpp
|
||||||
${CMAKE_SOURCE_DIR}/btservice/AndroidBluetoothService.cpp
|
${CMAKE_SOURCE_DIR}/btservice/AndroidBluetoothService.cpp
|
||||||
${CMAKE_SOURCE_DIR}/btservice/btservice.cpp
|
${CMAKE_SOURCE_DIR}/btservice/btservice.cpp
|
||||||
${CMAKE_SOURCE_DIR}/include/btservice/AndroidBluetoothServer.hpp
|
${CMAKE_SOURCE_DIR}/include/btservice/AndroidBluetoothServer.hpp
|
||||||
@ -42,6 +45,8 @@ add_library(openauto SHARED
|
|||||||
${CMAKE_SOURCE_DIR}/include/openauto/Configuration/IRecentAddressesList.hpp
|
${CMAKE_SOURCE_DIR}/include/openauto/Configuration/IRecentAddressesList.hpp
|
||||||
${CMAKE_SOURCE_DIR}/include/openauto/Configuration/HandednessOfTrafficType.hpp
|
${CMAKE_SOURCE_DIR}/include/openauto/Configuration/HandednessOfTrafficType.hpp
|
||||||
${CMAKE_SOURCE_DIR}/include/openauto/Configuration/BluetootAdapterType.hpp
|
${CMAKE_SOURCE_DIR}/include/openauto/Configuration/BluetootAdapterType.hpp
|
||||||
|
${CMAKE_SOURCE_DIR}/include/openauto/Service/NavigationStatusService.hpp
|
||||||
|
${CMAKE_SOURCE_DIR}/include/openauto/Service/MediaStatusService.hpp
|
||||||
${CMAKE_SOURCE_DIR}/include/openauto/Service/MediaAudioService.hpp
|
${CMAKE_SOURCE_DIR}/include/openauto/Service/MediaAudioService.hpp
|
||||||
${CMAKE_SOURCE_DIR}/include/openauto/Service/SensorService.hpp
|
${CMAKE_SOURCE_DIR}/include/openauto/Service/SensorService.hpp
|
||||||
${CMAKE_SOURCE_DIR}/include/openauto/Service/IPinger.hpp
|
${CMAKE_SOURCE_DIR}/include/openauto/Service/IPinger.hpp
|
||||||
@ -110,6 +115,7 @@ target_link_libraries(openauto PUBLIC
|
|||||||
Threads::Threads
|
Threads::Threads
|
||||||
${Boost_LIBRARIES}
|
${Boost_LIBRARIES}
|
||||||
aasdk
|
aasdk
|
||||||
|
h264
|
||||||
rtaudio
|
rtaudio
|
||||||
Qt5::Bluetooth
|
Qt5::Bluetooth
|
||||||
Qt5::MultimediaWidgets
|
Qt5::MultimediaWidgets
|
||||||
|
@ -35,6 +35,8 @@ const std::string Configuration::cVideoScreenDPIKey = "Video.ScreenDPI";
|
|||||||
const std::string Configuration::cVideoOMXLayerIndexKey = "Video.OMXLayerIndex";
|
const std::string Configuration::cVideoOMXLayerIndexKey = "Video.OMXLayerIndex";
|
||||||
const std::string Configuration::cVideoMarginWidth = "Video.MarginWidth";
|
const std::string Configuration::cVideoMarginWidth = "Video.MarginWidth";
|
||||||
const std::string Configuration::cVideoMarginHeight = "Video.MarginHeight";
|
const std::string Configuration::cVideoMarginHeight = "Video.MarginHeight";
|
||||||
|
const std::string Configuration::cVideoWhitescreenWorkaround = "Video.WhitesreenWorkaround";
|
||||||
|
|
||||||
|
|
||||||
const std::string Configuration::cAudioMusicAudioChannelEnabled = "Audio.MusicAudioChannelEnabled";
|
const std::string Configuration::cAudioMusicAudioChannelEnabled = "Audio.MusicAudioChannelEnabled";
|
||||||
const std::string Configuration::cAudioSpeechAudioChannelEnabled = "Audio.SpeechAudioChannelEnabled";
|
const std::string Configuration::cAudioSpeechAudioChannelEnabled = "Audio.SpeechAudioChannelEnabled";
|
||||||
@ -93,6 +95,7 @@ void Configuration::load()
|
|||||||
|
|
||||||
omxLayerIndex_ = iniConfig.get<int32_t>(cVideoOMXLayerIndexKey, 1);
|
omxLayerIndex_ = iniConfig.get<int32_t>(cVideoOMXLayerIndexKey, 1);
|
||||||
videoMargins_ = QRect(0, 0, iniConfig.get<int32_t>(cVideoMarginWidth, 0), iniConfig.get<int32_t>(cVideoMarginHeight, 0));
|
videoMargins_ = QRect(0, 0, iniConfig.get<int32_t>(cVideoMarginWidth, 0), iniConfig.get<int32_t>(cVideoMarginHeight, 0));
|
||||||
|
whitescreenWorkaround_ = iniConfig.get<bool>(cVideoWhitescreenWorkaround, true);
|
||||||
|
|
||||||
enableTouchscreen_ = iniConfig.get<bool>(cInputEnableTouchscreenKey, true);
|
enableTouchscreen_ = iniConfig.get<bool>(cInputEnableTouchscreenKey, true);
|
||||||
this->readButtonCodes(iniConfig);
|
this->readButtonCodes(iniConfig);
|
||||||
@ -130,6 +133,7 @@ void Configuration::reset()
|
|||||||
screenDPI_ = 140;
|
screenDPI_ = 140;
|
||||||
omxLayerIndex_ = 1;
|
omxLayerIndex_ = 1;
|
||||||
videoMargins_ = QRect(0, 0, 0, 0);
|
videoMargins_ = QRect(0, 0, 0, 0);
|
||||||
|
whitescreenWorkaround_ = true;
|
||||||
enableTouchscreen_ = true;
|
enableTouchscreen_ = true;
|
||||||
buttonCodes_.clear();
|
buttonCodes_.clear();
|
||||||
bluetoothAdapterType_ = BluetoothAdapterType::NONE;
|
bluetoothAdapterType_ = BluetoothAdapterType::NONE;
|
||||||
@ -151,6 +155,7 @@ void Configuration::save()
|
|||||||
iniConfig.put<int32_t>(cVideoOMXLayerIndexKey, omxLayerIndex_);
|
iniConfig.put<int32_t>(cVideoOMXLayerIndexKey, omxLayerIndex_);
|
||||||
iniConfig.put<uint32_t>(cVideoMarginWidth, videoMargins_.width());
|
iniConfig.put<uint32_t>(cVideoMarginWidth, videoMargins_.width());
|
||||||
iniConfig.put<uint32_t>(cVideoMarginHeight, videoMargins_.height());
|
iniConfig.put<uint32_t>(cVideoMarginHeight, videoMargins_.height());
|
||||||
|
iniConfig.put<bool>(cVideoWhitescreenWorkaround, whitescreenWorkaround_);
|
||||||
|
|
||||||
iniConfig.put<bool>(cInputEnableTouchscreenKey, enableTouchscreen_);
|
iniConfig.put<bool>(cInputEnableTouchscreenKey, enableTouchscreen_);
|
||||||
this->writeButtonCodes(iniConfig);
|
this->writeButtonCodes(iniConfig);
|
||||||
@ -240,6 +245,16 @@ QRect Configuration::getVideoMargins() const
|
|||||||
return videoMargins_;
|
return videoMargins_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Configuration::setWhitescreenWorkaround(bool value)
|
||||||
|
{
|
||||||
|
whitescreenWorkaround_ = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Configuration::getWhitescreenWorkaround() const
|
||||||
|
{
|
||||||
|
return whitescreenWorkaround_;
|
||||||
|
}
|
||||||
|
|
||||||
bool Configuration::getTouchscreenEnabled() const
|
bool Configuration::getTouchscreenEnabled() const
|
||||||
{
|
{
|
||||||
return enableTouchscreen_;
|
return enableTouchscreen_;
|
||||||
|
@ -15,12 +15,18 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with openauto. If not, see <http://www.gnu.org/licenses/>.
|
* along with openauto. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef USE_GST
|
#ifdef USE_GST
|
||||||
|
|
||||||
#include "aasdk/Common/Data.hpp"
|
#include "aasdk/Common/Data.hpp"
|
||||||
#include "openauto/Projection/GSTVideoOutput.hpp"
|
#include "openauto/Projection/GSTVideoOutput.hpp"
|
||||||
#include "OpenautoLog.hpp"
|
#include "OpenautoLog.hpp"
|
||||||
|
#include "h264_stream.h"
|
||||||
|
#include <QTimer>
|
||||||
|
// these are needed only for pretty printing of data, to be removed
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
namespace openauto
|
namespace openauto
|
||||||
{
|
{
|
||||||
@ -42,28 +48,13 @@ GSTVideoOutput::GSTVideoOutput(configuration::IConfiguration::Pointer configurat
|
|||||||
|
|
||||||
videoSink_ = surface_->videoSink();
|
videoSink_ = surface_->videoSink();
|
||||||
|
|
||||||
GError* error = nullptr;
|
|
||||||
const char* vidLaunchStr = "appsrc name=mysrc is-live=true block=false max-latency=100 do-timestamp=true stream-type=stream ! queue ! h264parse ! "
|
|
||||||
#ifdef RPI
|
|
||||||
#ifdef PI4
|
|
||||||
"v4l2h264dec ! "
|
|
||||||
#else
|
|
||||||
"omxh264dec ! "
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
"avdec_h264 ! "
|
|
||||||
#endif
|
|
||||||
"capsfilter caps=video/x-raw name=mycapsfilter";
|
|
||||||
#ifdef RPI
|
|
||||||
OPENAUTO_LOG(info) << "[GSTVideoOutput] RPI Build, running with " <<
|
|
||||||
#ifdef PI4
|
|
||||||
"v4l2h264dec";
|
|
||||||
#else
|
|
||||||
"omxh264dec";
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
vidPipeline_ = gst_parse_launch(vidLaunchStr, &error);
|
GError* error = nullptr;
|
||||||
|
std::string vidLaunchStr = "appsrc name=mysrc is-live=true block=false max-latency=100 do-timestamp=true stream-type=stream ! queue ! h264parse ! capssetter caps=\"video/x-h264,colorimetry=bt709\" ! ";
|
||||||
|
vidLaunchStr += ToPipeline(findPreferredVideoDecoder());
|
||||||
|
vidLaunchStr += " ! videocrop top=0 bottom=0 name=videocropper ! capsfilter caps=video/x-raw name=mycapsfilter";
|
||||||
|
|
||||||
|
vidPipeline_ = gst_parse_launch(vidLaunchStr.c_str(), &error);
|
||||||
GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(vidPipeline_));
|
GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(vidPipeline_));
|
||||||
gst_bus_add_watch(bus, (GstBusFunc)&GSTVideoOutput::busCallback, this);
|
gst_bus_add_watch(bus, (GstBusFunc)&GSTVideoOutput::busCallback, this);
|
||||||
gst_object_unref(bus);
|
gst_object_unref(bus);
|
||||||
@ -80,6 +71,8 @@ GSTVideoOutput::GSTVideoOutput(configuration::IConfiguration::Pointer configurat
|
|||||||
vidSrc_ = GST_APP_SRC(gst_bin_get_by_name(GST_BIN(vidPipeline_), "mysrc"));
|
vidSrc_ = GST_APP_SRC(gst_bin_get_by_name(GST_BIN(vidPipeline_), "mysrc"));
|
||||||
gst_app_src_set_stream_type(vidSrc_, GST_APP_STREAM_TYPE_STREAM);
|
gst_app_src_set_stream_type(vidSrc_, GST_APP_STREAM_TYPE_STREAM);
|
||||||
|
|
||||||
|
vidCrop_ = GST_VIDEO_FILTER(gst_bin_get_by_name(GST_BIN(vidPipeline_), "videocropper"));
|
||||||
|
|
||||||
connect(this, &GSTVideoOutput::startPlayback, this, &GSTVideoOutput::onStartPlayback, Qt::QueuedConnection);
|
connect(this, &GSTVideoOutput::startPlayback, this, &GSTVideoOutput::onStartPlayback, Qt::QueuedConnection);
|
||||||
connect(this, &GSTVideoOutput::stopPlayback, this, &GSTVideoOutput::onStopPlayback, Qt::QueuedConnection);
|
connect(this, &GSTVideoOutput::stopPlayback, this, &GSTVideoOutput::onStopPlayback, Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
@ -90,6 +83,27 @@ GSTVideoOutput::~GSTVideoOutput()
|
|||||||
gst_object_unref(vidSrc_);
|
gst_object_unref(vidSrc_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
H264_Decoder GSTVideoOutput::findPreferredVideoDecoder()
|
||||||
|
{
|
||||||
|
for (H264_Decoder decoder : H264_Decoder_Priority_List) {
|
||||||
|
GstElementFactory *decoder_factory = gst_element_factory_find (ToString(decoder));
|
||||||
|
if(decoder_factory != nullptr){
|
||||||
|
gst_object_unref(decoder_factory);
|
||||||
|
OPENAUTO_LOG(info) << "[GSTVideoOutput] Selecting the " << ToString(decoder) << " h264 decoder";
|
||||||
|
return decoder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OPENAUTO_LOG(error) << "[GSTVideoOutput] Couldn't find a decoder to use!";
|
||||||
|
return H264_Decoder::unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GSTVideoOutput::dumpDot()
|
||||||
|
{
|
||||||
|
gst_debug_bin_to_dot_file(GST_BIN(vidPipeline_), GST_DEBUG_GRAPH_SHOW_VERBOSE, "pipeline");
|
||||||
|
OPENAUTO_LOG(info) << "[GSTVideoOutput] Dumped dot debug info";
|
||||||
|
}
|
||||||
|
|
||||||
gboolean GSTVideoOutput::busCallback(GstBus*, GstMessage* message, gpointer*)
|
gboolean GSTVideoOutput::busCallback(GstBus*, GstMessage* message, gpointer*)
|
||||||
{
|
{
|
||||||
gchar* debug;
|
gchar* debug;
|
||||||
@ -165,6 +179,90 @@ bool GSTVideoOutput::init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GSTVideoOutput::write(uint64_t timestamp, const aasdk::common::DataConstBuffer& buffer)
|
void GSTVideoOutput::write(uint64_t timestamp, const aasdk::common::DataConstBuffer& buffer)
|
||||||
|
{
|
||||||
|
if(!firstHeaderParsed && this->configuration_->getWhitescreenWorkaround())
|
||||||
|
{
|
||||||
|
// I really really really hate this.
|
||||||
|
|
||||||
|
// Raspberry Pi hardware h264 decode appears broken if video_signal_type VUI parameters are given in the h264 header
|
||||||
|
// And we don't have control over Android Auto putting these parameters in (which it does.. on some model phones)
|
||||||
|
// So we pull in h264bitstream to edit this header on the fly
|
||||||
|
|
||||||
|
// This is not a fix, I want to be very clear about that. I don't know what else I'm breaking, or run the
|
||||||
|
// risk of breaking by doing this. This code should only remain here as long as the Pi Engineers haven't released
|
||||||
|
// a firmware/driver fix for this yet. An issue has been opened upstream at https://github.com/raspberrypi/firmware/issues/1673
|
||||||
|
|
||||||
|
// Android Auto seems nice enough to always start a message with a new h264 packet,
|
||||||
|
// but that doesn't mean we don't have multiple within the message.
|
||||||
|
// So if we have a message that _could_ fit two packets (which are delimited by 0x00000001)
|
||||||
|
// then we try to find the second and save the data it contains, while editing and replacing the first.
|
||||||
|
|
||||||
|
// This header should also always be within the first video message we receive from a device... I think
|
||||||
|
|
||||||
|
std::vector<uint8_t> delimit_sequence{0x00, 0x00, 0x00, 0x01};
|
||||||
|
std::vector<uint8_t>::iterator sequence_split;
|
||||||
|
std::vector<uint8_t> incoming_buffer(&buffer.cdata[0], &buffer.cdata[buffer.size]);
|
||||||
|
|
||||||
|
int nal_start, nal_end;
|
||||||
|
uint8_t* buf = (uint8_t *) buffer.cdata;
|
||||||
|
int len = buffer.size;
|
||||||
|
h264_stream_t* h = h264_new();
|
||||||
|
// finds the first NAL packet
|
||||||
|
find_nal_unit(buf, len, &nal_start, &nal_end);
|
||||||
|
// parses it
|
||||||
|
read_nal_unit(h, &buf[nal_start], nal_end - nal_start);
|
||||||
|
// wipe all the color description stuff that breaks Pis
|
||||||
|
h->sps->vui.video_signal_type_present_flag = 0x00;
|
||||||
|
h->sps->vui.video_format = 0x00;
|
||||||
|
h->sps->vui.video_full_range_flag = 0x00;
|
||||||
|
h->sps->vui.colour_description_present_flag = 0x00;
|
||||||
|
h->sps->vui.video_format = 0x00;
|
||||||
|
h->sps->vui.video_full_range_flag = 0x00;
|
||||||
|
h->sps->vui.colour_description_present_flag = 0x00;
|
||||||
|
h->sps->vui.colour_primaries = 0x00;
|
||||||
|
h->sps->vui.transfer_characteristics = 0x00;
|
||||||
|
h->sps->vui.matrix_coefficients = 0x00;
|
||||||
|
|
||||||
|
// grab some storage
|
||||||
|
uint8_t* out_buf = new uint8_t[30];
|
||||||
|
|
||||||
|
// write it to the storage's 3rd index, because h264bitstream seems to have a bug
|
||||||
|
// where it both doesn't write the delimiter, and it prepends a leading 0x00
|
||||||
|
len = write_nal_unit(h, &out_buf[3], 30) + 3;
|
||||||
|
// write the delimiter back
|
||||||
|
out_buf[0] = 0x00;
|
||||||
|
out_buf[1] = 0x00;
|
||||||
|
out_buf[2] = 0x00;
|
||||||
|
out_buf[3] = 0x01;
|
||||||
|
|
||||||
|
// output to gstreamer
|
||||||
|
GstBuffer* buffer_ = gst_buffer_new_and_alloc(len);
|
||||||
|
gst_buffer_fill(buffer_, 0, out_buf, len);
|
||||||
|
int ret = gst_app_src_push_buffer((GstAppSrc*)vidSrc_, buffer_);
|
||||||
|
if(ret != GST_FLOW_OK)
|
||||||
|
{
|
||||||
|
OPENAUTO_LOG(info) << "[GSTVideoOutput] Injecting header failed";
|
||||||
|
}
|
||||||
|
|
||||||
|
// then check if there's data we need to save
|
||||||
|
if(incoming_buffer.size() >= 8){
|
||||||
|
sequence_split = std::search(incoming_buffer.begin()+4, incoming_buffer.end(), delimit_sequence.begin(), delimit_sequence.end());
|
||||||
|
if(sequence_split != incoming_buffer.end()){
|
||||||
|
std::vector<uint8_t> incoming_data_saved(sequence_split, incoming_buffer.end());
|
||||||
|
GstBuffer* buffer_ = gst_buffer_new_and_alloc(incoming_data_saved.size());
|
||||||
|
gst_buffer_fill(buffer_, 0, incoming_data_saved.data(), incoming_data_saved.size());
|
||||||
|
int ret = gst_app_src_push_buffer((GstAppSrc*)vidSrc_, buffer_);
|
||||||
|
if(ret != GST_FLOW_OK)
|
||||||
|
{
|
||||||
|
OPENAUTO_LOG(info) << "[GSTVideoOutput] Injecting partial header failed";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OPENAUTO_LOG(info) << "[GSTVideoOutput] Intercepted and replaced h264 header";
|
||||||
|
|
||||||
|
firstHeaderParsed=true;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
GstBuffer* buffer_ = gst_buffer_new_and_alloc(buffer.size);
|
GstBuffer* buffer_ = gst_buffer_new_and_alloc(buffer.size);
|
||||||
gst_buffer_fill(buffer_, 0, buffer.cdata, buffer.size);
|
gst_buffer_fill(buffer_, 0, buffer.cdata, buffer.size);
|
||||||
@ -174,9 +272,11 @@ void GSTVideoOutput::write(uint64_t timestamp, const aasdk::common::DataConstBuf
|
|||||||
OPENAUTO_LOG(info) << "[GSTVideoOutput] push buffer returned " << ret << " for " << buffer.size << "bytes";
|
OPENAUTO_LOG(info) << "[GSTVideoOutput] push buffer returned " << ret << " for " << buffer.size << "bytes";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GSTVideoOutput::onStartPlayback()
|
void GSTVideoOutput::onStartPlayback()
|
||||||
{
|
{
|
||||||
|
firstHeaderParsed = false;
|
||||||
if(activeCallback_ != nullptr)
|
if(activeCallback_ != nullptr)
|
||||||
{
|
{
|
||||||
activeCallback_(true);
|
activeCallback_(true);
|
||||||
@ -195,6 +295,7 @@ void GSTVideoOutput::onStartPlayback()
|
|||||||
videoWidget_->resize(videoContainer_->size());
|
videoWidget_->resize(videoContainer_->size());
|
||||||
}
|
}
|
||||||
videoWidget_->show();
|
videoWidget_->show();
|
||||||
|
QTimer::singleShot(10000, this, SLOT(dumpDot()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GSTVideoOutput::stop()
|
void GSTVideoOutput::stop()
|
||||||
@ -204,6 +305,8 @@ void GSTVideoOutput::stop()
|
|||||||
|
|
||||||
void GSTVideoOutput::onStopPlayback()
|
void GSTVideoOutput::onStopPlayback()
|
||||||
{
|
{
|
||||||
|
firstHeaderParsed = false;
|
||||||
|
|
||||||
if(activeCallback_ != nullptr)
|
if(activeCallback_ != nullptr)
|
||||||
{
|
{
|
||||||
activeCallback_(false);
|
activeCallback_(false);
|
||||||
@ -222,6 +325,50 @@ void GSTVideoOutput::resize()
|
|||||||
{
|
{
|
||||||
videoWidget_->resize(videoContainer_->size());
|
videoWidget_->resize(videoContainer_->size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int width = 0;
|
||||||
|
int height = 0;
|
||||||
|
int containerWidth = videoContainer_->width();
|
||||||
|
int containerHeight = videoContainer_->height();
|
||||||
|
|
||||||
|
switch(this->getVideoResolution()){
|
||||||
|
case aasdk::proto::enums::VideoResolution_Enum__1080p:
|
||||||
|
width = 1920;
|
||||||
|
height = 1080;
|
||||||
|
break;
|
||||||
|
case aasdk::proto::enums::VideoResolution_Enum__720p:
|
||||||
|
width = 1280;
|
||||||
|
height = 720;
|
||||||
|
break;
|
||||||
|
case aasdk::proto::enums::VideoResolution_Enum__480p:
|
||||||
|
width = 800;
|
||||||
|
height = 480;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
double marginWidth = 0;
|
||||||
|
double marginHeight = 0;
|
||||||
|
|
||||||
|
double widthRatio = (double)containerWidth / width;
|
||||||
|
double heightRatio = (double)containerHeight / height;
|
||||||
|
|
||||||
|
if(widthRatio > heightRatio){
|
||||||
|
//cropping height
|
||||||
|
marginHeight = (widthRatio * height - containerHeight)/widthRatio;
|
||||||
|
marginHeight /= 2;
|
||||||
|
}else{
|
||||||
|
//cropping width
|
||||||
|
marginWidth = (heightRatio * width - containerWidth)/heightRatio;
|
||||||
|
marginWidth /= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
OPENAUTO_LOG(info) << "[GSTVideoOutput] Android Auto is "<< width << "x" << height << ", calculated margins of: " << marginWidth << "x" << marginHeight;
|
||||||
|
g_object_set(vidCrop_, "top", (int)marginHeight, nullptr);
|
||||||
|
g_object_set(vidCrop_, "bottom", (int)marginHeight, nullptr);
|
||||||
|
g_object_set(vidCrop_, "left", (int)marginWidth, nullptr);
|
||||||
|
g_object_set(vidCrop_, "right", (int)marginWidth, nullptr);
|
||||||
|
this->configuration_->setVideoMargins(QRect(0,0,(int)(marginWidth*2), (int)(marginHeight*2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "OpenautoLog.hpp"
|
#include "OpenautoLog.hpp"
|
||||||
#include "openauto/Projection/IInputDeviceEventHandler.hpp"
|
#include "openauto/Projection/IInputDeviceEventHandler.hpp"
|
||||||
#include "openauto/Projection/InputDevice.hpp"
|
#include "openauto/Projection/InputDevice.hpp"
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
namespace openauto
|
namespace openauto
|
||||||
{
|
{
|
||||||
@ -33,6 +34,7 @@ InputDevice::InputDevice(QObject& parent, configuration::IConfiguration::Pointer
|
|||||||
, eventHandler_(nullptr)
|
, eventHandler_(nullptr)
|
||||||
{
|
{
|
||||||
this->moveToThread(parent.thread());
|
this->moveToThread(parent.thread());
|
||||||
|
pointer_id_queue.push(INT_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputDevice::start(IInputDeviceEventHandler& eventHandler)
|
void InputDevice::start(IInputDeviceEventHandler& eventHandler)
|
||||||
@ -67,10 +69,14 @@ bool InputDevice::eventFilter(QObject* obj, QEvent* event)
|
|||||||
return this->handleKeyEvent(event, key);
|
return this->handleKeyEvent(event, key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease || event->type() == QEvent::MouseMove)
|
else if(event->type() == QEvent::TouchBegin || event->type() == QEvent::TouchUpdate || event->type() == QEvent::TouchEnd || event->type() == QEvent::TouchCancel)
|
||||||
{
|
{
|
||||||
return this->handleTouchEvent(event);
|
return this->handleTouchEvent(event);
|
||||||
}
|
}
|
||||||
|
else if(event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease || event->type() == QEvent::MouseMove)
|
||||||
|
{
|
||||||
|
return this->handleMouseEvent(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return QObject::eventFilter(obj, event);
|
return QObject::eventFilter(obj, event);
|
||||||
@ -175,7 +181,6 @@ bool InputDevice::handleKeyEvent(QEvent* event, QKeyEvent* key)
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputDevice::handleTouchEvent(QEvent* event)
|
bool InputDevice::handleTouchEvent(QEvent* event)
|
||||||
{
|
{
|
||||||
if(!configuration_->getTouchscreenEnabled())
|
if(!configuration_->getTouchscreenEnabled())
|
||||||
@ -183,6 +188,81 @@ bool InputDevice::handleTouchEvent(QEvent* event)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QTouchEvent* qtTouchEvent = static_cast<QTouchEvent*>(event);
|
||||||
|
aasdk::proto::enums::TouchAction::Enum type;
|
||||||
|
auto timestamp = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now().time_since_epoch());
|
||||||
|
aasdk::proto::messages::InputEventIndication inputEventIndication;
|
||||||
|
inputEventIndication.set_timestamp(timestamp.count());
|
||||||
|
auto touchEvent = inputEventIndication.mutable_touch_event();
|
||||||
|
switch(event->type()){
|
||||||
|
case QEvent::TouchBegin:
|
||||||
|
type = aasdk::proto::enums::TouchAction::PRESS;
|
||||||
|
break;
|
||||||
|
case QEvent::TouchUpdate:
|
||||||
|
if(qtTouchEvent->touchPointStates().testFlag(Qt::TouchPointPressed)) type = aasdk::proto::enums::TouchAction::POINTER_DOWN;
|
||||||
|
else if(qtTouchEvent->touchPointStates().testFlag(Qt::TouchPointReleased)) type = aasdk::proto::enums::TouchAction::POINTER_UP;
|
||||||
|
else{
|
||||||
|
type = aasdk::proto::enums::TouchAction::DRAG;
|
||||||
|
touchEvent->set_action_index(0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case QEvent::TouchEnd:
|
||||||
|
type = aasdk::proto::enums::TouchAction::RELEASE;
|
||||||
|
break;
|
||||||
|
case QEvent::TouchCancel:
|
||||||
|
type = aasdk::proto::enums::TouchAction::RELEASE;
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
touchEvent->set_touch_action(type);
|
||||||
|
|
||||||
|
auto pointers = qtTouchEvent->touchPoints();
|
||||||
|
|
||||||
|
// What's with this pointer map and pointer id queue?
|
||||||
|
// Pointers get a unique id during their lifespan, and android auto gets pissy when you try and just use the unique id qt assigns
|
||||||
|
// but it's happier with smaller valued ids
|
||||||
|
// and since there are no garuntees about id range, or similar (because of drivers and whatnot)
|
||||||
|
// pointer id queue is a min heap, with the first item being the next availible "smaller id"
|
||||||
|
// and pointer maps stores the qt id: small id relation
|
||||||
|
// the pointer id queue will expand as needed
|
||||||
|
|
||||||
|
// I kinda hate this, but it works
|
||||||
|
|
||||||
|
for(int i=0; i<pointers.count(); i++)
|
||||||
|
{
|
||||||
|
if(pointers[i].state() == Qt::TouchPointPressed){
|
||||||
|
touchEvent->set_action_index(i);
|
||||||
|
if(pointer_id_queue.top() == INT_MAX){
|
||||||
|
pointer_id_queue.push(max_pointers++);
|
||||||
|
}
|
||||||
|
pointer_map.insert(pointers[i].id(), pointer_id_queue.top());
|
||||||
|
pointer_id_queue.pop();
|
||||||
|
}
|
||||||
|
else if(pointers[i].state() == Qt::TouchPointReleased){
|
||||||
|
touchEvent->set_action_index(i);
|
||||||
|
pointer_id_queue.push(pointer_map.take(pointers[i].id()));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto touchLocation = touchEvent->add_touch_location();
|
||||||
|
touchLocation->set_x((static_cast<float>(pointers[i].pos().x()) / touchscreenGeometry_.width()) * displayGeometry_.width());
|
||||||
|
touchLocation->set_y((static_cast<float>(pointers[i].pos().y()) / touchscreenGeometry_.height()) * displayGeometry_.height());
|
||||||
|
touchLocation->set_pointer_id(pointer_map[pointers[i].id()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
eventHandler_->onTouchEvent(inputEventIndication);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
bool InputDevice::handleMouseEvent(QEvent* event)
|
||||||
|
{
|
||||||
|
if(!configuration_->getTouchscreenEnabled())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
aasdk::proto::enums::TouchAction::Enum type;
|
aasdk::proto::enums::TouchAction::Enum type;
|
||||||
|
|
||||||
switch(event->type())
|
switch(event->type())
|
||||||
@ -205,7 +285,7 @@ bool InputDevice::handleTouchEvent(QEvent* event)
|
|||||||
{
|
{
|
||||||
const uint32_t x = (static_cast<float>(mouse->pos().x()) / touchscreenGeometry_.width()) * displayGeometry_.width();
|
const uint32_t x = (static_cast<float>(mouse->pos().x()) / touchscreenGeometry_.width()) * displayGeometry_.width();
|
||||||
const uint32_t y = (static_cast<float>(mouse->pos().y()) / touchscreenGeometry_.height()) * displayGeometry_.height();
|
const uint32_t y = (static_cast<float>(mouse->pos().y()) / touchscreenGeometry_.height()) * displayGeometry_.height();
|
||||||
eventHandler_->onTouchEvent({type, x, y, 0});
|
eventHandler_->onMouseEvent({type, x, y, 0});
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -24,6 +24,8 @@ namespace openauto
|
|||||||
namespace projection
|
namespace projection
|
||||||
{
|
{
|
||||||
|
|
||||||
|
std::mutex RtAudioOutput::mutex_;
|
||||||
|
|
||||||
RtAudioOutput::RtAudioOutput(uint32_t channelCount, uint32_t sampleSize, uint32_t sampleRate)
|
RtAudioOutput::RtAudioOutput(uint32_t channelCount, uint32_t sampleSize, uint32_t sampleRate)
|
||||||
: channelCount_(channelCount)
|
: channelCount_(channelCount)
|
||||||
, sampleSize_(sampleSize)
|
, sampleSize_(sampleSize)
|
||||||
|
@ -30,7 +30,7 @@ InputService::InputService(boost::asio::io_service& ioService, aasdk::messenger:
|
|||||||
, channel_(std::make_shared<aasdk::channel::input::InputServiceChannel>(strand_, std::move(messenger)))
|
, channel_(std::make_shared<aasdk::channel::input::InputServiceChannel>(strand_, std::move(messenger)))
|
||||||
, inputDevice_(std::move(inputDevice))
|
, inputDevice_(std::move(inputDevice))
|
||||||
{
|
{
|
||||||
|
OPENAUTO_LOG(info) << "[InputService] Created";
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputService::start()
|
void InputService::start()
|
||||||
@ -39,6 +39,7 @@ void InputService::start()
|
|||||||
OPENAUTO_LOG(info) << "[InputService] start.";
|
OPENAUTO_LOG(info) << "[InputService] start.";
|
||||||
channel_->receive(this->shared_from_this());
|
channel_->receive(this->shared_from_this());
|
||||||
});
|
});
|
||||||
|
serviceActive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputService::stop()
|
void InputService::stop()
|
||||||
@ -47,6 +48,7 @@ void InputService::stop()
|
|||||||
OPENAUTO_LOG(info) << "[InputService] stop.";
|
OPENAUTO_LOG(info) << "[InputService] stop.";
|
||||||
inputDevice_->stop();
|
inputDevice_->stop();
|
||||||
});
|
});
|
||||||
|
serviceActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputService::fillFeatures(aasdk::proto::messages::ServiceDiscoveryResponse& response)
|
void InputService::fillFeatures(aasdk::proto::messages::ServiceDiscoveryResponse& response)
|
||||||
@ -128,11 +130,12 @@ void InputService::onBindingRequest(const aasdk::proto::messages::BindingRequest
|
|||||||
|
|
||||||
void InputService::onChannelError(const aasdk::error::Error& e)
|
void InputService::onChannelError(const aasdk::error::Error& e)
|
||||||
{
|
{
|
||||||
OPENAUTO_LOG(error) << "[SensorService] channel error: " << e.what();
|
OPENAUTO_LOG(error) << "[InputService] channel error: " << e.what();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputService::onButtonEvent(const projection::ButtonEvent& event)
|
void InputService::onButtonEvent(const projection::ButtonEvent& event)
|
||||||
{
|
{
|
||||||
|
if(!serviceActive) return;
|
||||||
auto timestamp = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now().time_since_epoch());
|
auto timestamp = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now().time_since_epoch());
|
||||||
|
|
||||||
strand_.dispatch([this, self = this->shared_from_this(), event = std::move(event), timestamp = std::move(timestamp)]() {
|
strand_.dispatch([this, self = this->shared_from_this(), event = std::move(event), timestamp = std::move(timestamp)]() {
|
||||||
@ -160,7 +163,39 @@ void InputService::onButtonEvent(const projection::ButtonEvent& event)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputService::onTouchEvent(const projection::TouchEvent& event)
|
void InputService::sendButtonPress(aasdk::proto::enums::ButtonCode::Enum buttonCode, projection::WheelDirection wheelDirection, projection::ButtonEventType buttonEventType)
|
||||||
|
{
|
||||||
|
OPENAUTO_LOG(info) << "[InputService] injecting button press";
|
||||||
|
if(buttonCode == aasdk::proto::enums::ButtonCode::SCROLL_WHEEL)
|
||||||
|
{
|
||||||
|
onButtonEvent({projection::ButtonEventType::NONE, wheelDirection, buttonCode});
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(buttonEventType == projection::ButtonEventType::NONE){
|
||||||
|
onButtonEvent({projection::ButtonEventType::PRESS, projection::WheelDirection::NONE, buttonCode});
|
||||||
|
onButtonEvent({projection::ButtonEventType::RELEASE, projection::WheelDirection::NONE, buttonCode});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
onButtonEvent({buttonEventType, projection::WheelDirection::NONE, buttonCode});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputService::onTouchEvent(aasdk::proto::messages::InputEventIndication inputEventIndication)
|
||||||
|
{
|
||||||
|
|
||||||
|
strand_.dispatch([this, self = this->shared_from_this(), inputEventIndication = std::move(inputEventIndication)]() {
|
||||||
|
|
||||||
|
auto promise = aasdk::channel::SendPromise::defer(strand_);
|
||||||
|
promise->then([]() {}, std::bind(&InputService::onChannelError, this->shared_from_this(), std::placeholders::_1));
|
||||||
|
channel_->sendInputEventIndication(inputEventIndication, std::move(promise));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputService::onMouseEvent(const projection::TouchEvent& event)
|
||||||
{
|
{
|
||||||
auto timestamp = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now().time_since_epoch());
|
auto timestamp = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now().time_since_epoch());
|
||||||
|
|
||||||
|
97
openauto/Service/MediaStatusService.cpp
Normal file
97
openauto/Service/MediaStatusService.cpp
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
#include "OpenautoLog.hpp"
|
||||||
|
#include "openauto/Service/MediaStatusService.hpp"
|
||||||
|
#include "openauto/Service/IAndroidAutoInterface.hpp"
|
||||||
|
|
||||||
|
namespace openauto
|
||||||
|
{
|
||||||
|
namespace service
|
||||||
|
{
|
||||||
|
|
||||||
|
MediaStatusService::MediaStatusService(boost::asio::io_service& ioService, aasdk::messenger::IMessenger::Pointer messenger, IAndroidAutoInterface* aa_interface)
|
||||||
|
: strand_(ioService)
|
||||||
|
, channel_(std::make_shared<aasdk::channel::av::MediaStatusServiceChannel>(strand_, std::move(messenger)))
|
||||||
|
{
|
||||||
|
aa_interface_ = aa_interface;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaStatusService::start()
|
||||||
|
{
|
||||||
|
strand_.dispatch([this, self = this->shared_from_this()]() {
|
||||||
|
OPENAUTO_LOG(info) << "[MediaStatusService] start.";
|
||||||
|
channel_->receive(this->shared_from_this());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaStatusService::stop()
|
||||||
|
{
|
||||||
|
strand_.dispatch([this, self = this->shared_from_this()]() {
|
||||||
|
OPENAUTO_LOG(info) << "[MediaStatusService] stop.";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaStatusService::fillFeatures(aasdk::proto::messages::ServiceDiscoveryResponse& response)
|
||||||
|
{
|
||||||
|
OPENAUTO_LOG(info) << "[MediaStatusService] fill features";
|
||||||
|
|
||||||
|
auto* channelDescriptor = response.add_channels();
|
||||||
|
auto mediaStatusChannel = channelDescriptor->mutable_media_infochannel();
|
||||||
|
channelDescriptor->set_channel_id(static_cast<uint32_t>(channel_->getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaStatusService::onChannelOpenRequest(const aasdk::proto::messages::ChannelOpenRequest& request)
|
||||||
|
{
|
||||||
|
OPENAUTO_LOG(info) << "[MediaStatusService] open request, priority: " << request.priority();
|
||||||
|
const aasdk::proto::enums::Status::Enum status = aasdk::proto::enums::Status::OK;
|
||||||
|
OPENAUTO_LOG(info) << "[MediaStatusService] open status: " << status;
|
||||||
|
|
||||||
|
aasdk::proto::messages::ChannelOpenResponse response;
|
||||||
|
response.set_status(status);
|
||||||
|
|
||||||
|
auto promise = aasdk::channel::SendPromise::defer(strand_);
|
||||||
|
promise->then([]() {}, std::bind(&MediaStatusService::onChannelError, this->shared_from_this(), std::placeholders::_1));
|
||||||
|
channel_->sendChannelOpenResponse(response, std::move(promise));
|
||||||
|
|
||||||
|
channel_->receive(this->shared_from_this());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MediaStatusService::onChannelError(const aasdk::error::Error& e)
|
||||||
|
{
|
||||||
|
OPENAUTO_LOG(error) << "[MediaStatusService] channel error: " << e.what();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaStatusService::onMetadataUpdate(const aasdk::proto::messages::MediaInfoChannelMetadataData& metadata)
|
||||||
|
{
|
||||||
|
OPENAUTO_LOG(info) << "[MediaStatusService] Metadata update"
|
||||||
|
<< ", track: " << metadata.track_name()
|
||||||
|
<< (metadata.has_artist_name()?", artist: ":"") << (metadata.has_artist_name()?metadata.artist_name():"")
|
||||||
|
<< (metadata.has_album_name()?", album: ":"") << (metadata.has_album_name()?metadata.album_name():"")
|
||||||
|
<< ", length: " << metadata.track_length();
|
||||||
|
if(aa_interface_ != NULL)
|
||||||
|
{
|
||||||
|
aa_interface_->mediaMetadataUpdate(metadata);
|
||||||
|
}
|
||||||
|
channel_->receive(this->shared_from_this());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaStatusService::onPlaybackUpdate(const aasdk::proto::messages::MediaInfoChannelPlaybackData& playback)
|
||||||
|
{
|
||||||
|
OPENAUTO_LOG(info) << "[MediaStatusService] Playback update"
|
||||||
|
<< ", source: " << playback.media_source()
|
||||||
|
<< ", state: " << playback.playback_state()
|
||||||
|
<< ", progress: " << playback.track_progress();
|
||||||
|
if(aa_interface_ != NULL)
|
||||||
|
{
|
||||||
|
aa_interface_->mediaPlaybackUpdate(playback);
|
||||||
|
}
|
||||||
|
channel_->receive(this->shared_from_this());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaStatusService::setAndroidAutoInterface(IAndroidAutoInterface* aa_interface)
|
||||||
|
{
|
||||||
|
this->aa_interface_ = aa_interface;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
119
openauto/Service/NavigationStatusService.cpp
Normal file
119
openauto/Service/NavigationStatusService.cpp
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
#include "OpenautoLog.hpp"
|
||||||
|
#include "openauto/Service/NavigationStatusService.hpp"
|
||||||
|
#include "aasdk_proto/ManeuverTypeEnum.pb.h"
|
||||||
|
#include "aasdk_proto/ManeuverDirectionEnum.pb.h"
|
||||||
|
#include "aasdk_proto/DistanceUnitEnum.pb.h"
|
||||||
|
#include "openauto/Service/IAndroidAutoInterface.hpp"
|
||||||
|
|
||||||
|
namespace openauto
|
||||||
|
{
|
||||||
|
namespace service
|
||||||
|
{
|
||||||
|
|
||||||
|
NavigationStatusService::NavigationStatusService(boost::asio::io_service& ioService, aasdk::messenger::IMessenger::Pointer messenger, IAndroidAutoInterface* aa_interface)
|
||||||
|
: strand_(ioService)
|
||||||
|
, channel_(std::make_shared<aasdk::channel::navigation::NavigationStatusServiceChannel>(strand_, std::move(messenger)))
|
||||||
|
{
|
||||||
|
this->aa_interface_ = aa_interface;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NavigationStatusService::start()
|
||||||
|
{
|
||||||
|
strand_.dispatch([this, self = this->shared_from_this()]() {
|
||||||
|
OPENAUTO_LOG(info) << "[NavigationStatusService] start.";
|
||||||
|
channel_->receive(this->shared_from_this());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void NavigationStatusService::stop()
|
||||||
|
{
|
||||||
|
strand_.dispatch([this, self = this->shared_from_this()]() {
|
||||||
|
OPENAUTO_LOG(info) << "[NavigationStatusService] stop.";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void NavigationStatusService::fillFeatures(aasdk::proto::messages::ServiceDiscoveryResponse& response)
|
||||||
|
{
|
||||||
|
OPENAUTO_LOG(info) << "[NavigationStatusService] fill features";
|
||||||
|
|
||||||
|
auto* channelDescriptor = response.add_channels();
|
||||||
|
channelDescriptor->set_channel_id(static_cast<uint32_t>(channel_->getId()));
|
||||||
|
auto navStatusChannel = channelDescriptor->mutable_navigation_channel();
|
||||||
|
navStatusChannel->set_minimum_interval_ms(1000);
|
||||||
|
navStatusChannel->set_type(aasdk::proto::enums::NavigationTurnType::IMAGE);
|
||||||
|
auto* imageOptions = new aasdk::proto::data::NavigationImageOptions();
|
||||||
|
imageOptions->set_colour_depth_bits(16);
|
||||||
|
imageOptions->set_height(256);
|
||||||
|
imageOptions->set_width(256);
|
||||||
|
imageOptions->set_dunno(255);
|
||||||
|
navStatusChannel->set_allocated_image_options(imageOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NavigationStatusService::onChannelOpenRequest(const aasdk::proto::messages::ChannelOpenRequest& request)
|
||||||
|
{
|
||||||
|
OPENAUTO_LOG(info) << "[NavigationStatusService] open request, priority: " << request.priority();
|
||||||
|
const aasdk::proto::enums::Status::Enum status = aasdk::proto::enums::Status::OK;
|
||||||
|
OPENAUTO_LOG(info) << "[NavigationStatusService] open status: " << status;
|
||||||
|
|
||||||
|
aasdk::proto::messages::ChannelOpenResponse response;
|
||||||
|
response.set_status(status);
|
||||||
|
|
||||||
|
auto promise = aasdk::channel::SendPromise::defer(strand_);
|
||||||
|
promise->then([]() {}, std::bind(&NavigationStatusService::onChannelError, this->shared_from_this(), std::placeholders::_1));
|
||||||
|
channel_->sendChannelOpenResponse(response, std::move(promise));
|
||||||
|
|
||||||
|
channel_->receive(this->shared_from_this());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void NavigationStatusService::onChannelError(const aasdk::error::Error& e)
|
||||||
|
{
|
||||||
|
OPENAUTO_LOG(error) << "[NavigationStatusService] channel error: " << e.what();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NavigationStatusService::onStatusUpdate(const aasdk::proto::messages::NavigationStatus& navStatus)
|
||||||
|
{
|
||||||
|
OPENAUTO_LOG(info) << "[NavigationStatusService] Navigation Status Update"
|
||||||
|
<< ", Status: " << aasdk::proto::messages::NavigationStatus_Enum_Name(navStatus.status());
|
||||||
|
if(aa_interface_ != NULL)
|
||||||
|
{
|
||||||
|
aa_interface_->navigationStatusUpdate(navStatus);
|
||||||
|
}
|
||||||
|
channel_->receive(this->shared_from_this());
|
||||||
|
}
|
||||||
|
|
||||||
|
void NavigationStatusService::onTurnEvent(const aasdk::proto::messages::NavigationTurnEvent& turnEvent)
|
||||||
|
{
|
||||||
|
OPENAUTO_LOG(info) << "[NavigationStatusService] Turn Event"
|
||||||
|
<< ", Street: " << turnEvent.street_name()
|
||||||
|
<< ", Maneuver: " << aasdk::proto::enums::ManeuverDirection_Enum_Name(turnEvent.maneuverdirection()) << " " << aasdk::proto::enums::ManeuverType_Enum_Name(turnEvent.maneuvertype());
|
||||||
|
if(aa_interface_ != NULL)
|
||||||
|
{
|
||||||
|
aa_interface_->navigationTurnEvent(turnEvent);
|
||||||
|
}
|
||||||
|
channel_->receive(this->shared_from_this());
|
||||||
|
}
|
||||||
|
|
||||||
|
void NavigationStatusService::onDistanceEvent(const aasdk::proto::messages::NavigationDistanceEvent& distanceEvent)
|
||||||
|
{
|
||||||
|
OPENAUTO_LOG(info) << "[NavigationStatusService] Distance Event"
|
||||||
|
<< ", Distance (meters): " << distanceEvent.meters()
|
||||||
|
<< ", Time To Turn (seconds): " << distanceEvent.timetostepseconds()
|
||||||
|
<< ", Distance: " << distanceEvent.distancetostepmillis()/1000.0
|
||||||
|
<< " ("<<aasdk::proto::enums::DistanceUnit_Enum_Name(distanceEvent.distanceunit())<<")";
|
||||||
|
if(aa_interface_ != NULL)
|
||||||
|
{
|
||||||
|
aa_interface_->navigationDistanceEvent(distanceEvent);
|
||||||
|
}
|
||||||
|
channel_->receive(this->shared_from_this());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void NavigationStatusService::setAndroidAutoInterface(IAndroidAutoInterface* aa_interface)
|
||||||
|
{
|
||||||
|
this->aa_interface_ = aa_interface;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -54,7 +54,6 @@ void SensorService::fillFeatures(aasdk::proto::messages::ServiceDiscoveryRespons
|
|||||||
|
|
||||||
auto* channelDescriptor = response.add_channels();
|
auto* channelDescriptor = response.add_channels();
|
||||||
channelDescriptor->set_channel_id(static_cast<uint32_t>(channel_->getId()));
|
channelDescriptor->set_channel_id(static_cast<uint32_t>(channel_->getId()));
|
||||||
|
|
||||||
auto* sensorChannel = channelDescriptor->mutable_sensor_channel();
|
auto* sensorChannel = channelDescriptor->mutable_sensor_channel();
|
||||||
sensorChannel->add_sensors()->set_type(aasdk::proto::enums::SensorType::DRIVING_STATUS);
|
sensorChannel->add_sensors()->set_type(aasdk::proto::enums::SensorType::DRIVING_STATUS);
|
||||||
//sensorChannel->add_sensors()->set_type(aasdk::proto::enums::SensorType::LOCATION);
|
//sensorChannel->add_sensors()->set_type(aasdk::proto::enums::SensorType::LOCATION);
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include "openauto/Service/SensorService.hpp"
|
#include "openauto/Service/SensorService.hpp"
|
||||||
#include "openauto/Service/BluetoothService.hpp"
|
#include "openauto/Service/BluetoothService.hpp"
|
||||||
#include "openauto/Service/InputService.hpp"
|
#include "openauto/Service/InputService.hpp"
|
||||||
|
#include "openauto/Service/NavigationStatusService.hpp"
|
||||||
#include "openauto/Projection/QtVideoOutput.hpp"
|
#include "openauto/Projection/QtVideoOutput.hpp"
|
||||||
#include "openauto/Projection/GSTVideoOutput.hpp"
|
#include "openauto/Projection/GSTVideoOutput.hpp"
|
||||||
#include "openauto/Projection/OMXVideoOutput.hpp"
|
#include "openauto/Projection/OMXVideoOutput.hpp"
|
||||||
@ -40,12 +41,13 @@
|
|||||||
#include "openauto/Projection/LocalBluetoothDevice.hpp"
|
#include "openauto/Projection/LocalBluetoothDevice.hpp"
|
||||||
#include "openauto/Projection/RemoteBluetoothDevice.hpp"
|
#include "openauto/Projection/RemoteBluetoothDevice.hpp"
|
||||||
#include "openauto/Projection/DummyBluetoothDevice.hpp"
|
#include "openauto/Projection/DummyBluetoothDevice.hpp"
|
||||||
|
#include "openauto/Service/IAndroidAutoInterface.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace openauto
|
namespace openauto
|
||||||
{
|
{
|
||||||
namespace service
|
namespace service
|
||||||
{
|
{
|
||||||
|
|
||||||
ServiceFactory::ServiceFactory(boost::asio::io_service& ioService, configuration::IConfiguration::Pointer configuration, QWidget *activeArea, std::function<void(bool)> activeCallback, bool nightMode)
|
ServiceFactory::ServiceFactory(boost::asio::io_service& ioService, configuration::IConfiguration::Pointer configuration, QWidget *activeArea, std::function<void(bool)> activeCallback, bool nightMode)
|
||||||
: ioService_(ioService)
|
: ioService_(ioService)
|
||||||
, configuration_(std::move(configuration))
|
, configuration_(std::move(configuration))
|
||||||
@ -62,6 +64,7 @@ ServiceFactory::ServiceFactory(boost::asio::io_service& ioService, configuration
|
|||||||
, btservice_(configuration_)
|
, btservice_(configuration_)
|
||||||
, nightMode_(nightMode)
|
, nightMode_(nightMode)
|
||||||
{
|
{
|
||||||
|
OPENAUTO_LOG(info) << "SERVICE FACTORY INITED";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,8 +82,16 @@ ServiceList ServiceFactory::create(aasdk::messenger::IMessenger::Pointer messeng
|
|||||||
|
|
||||||
serviceList.emplace_back(this->createVideoService(messenger));
|
serviceList.emplace_back(this->createVideoService(messenger));
|
||||||
serviceList.emplace_back(this->createBluetoothService(messenger));
|
serviceList.emplace_back(this->createBluetoothService(messenger));
|
||||||
serviceList.emplace_back(this->createInputService(messenger));
|
std::shared_ptr<NavigationStatusService> navStatusService = this->createNavigationStatusService(messenger);
|
||||||
|
navStatusService_ = navStatusService;
|
||||||
|
serviceList.emplace_back(navStatusService);
|
||||||
|
std::shared_ptr<MediaStatusService> mediaStatusService = this->createMediaStatusService(messenger);
|
||||||
|
mediaStatusService_ = mediaStatusService;
|
||||||
|
serviceList.emplace_back(mediaStatusService);
|
||||||
|
|
||||||
|
std::shared_ptr<InputService> inputService = this->createInputService(messenger);
|
||||||
|
inputService_ = inputService;
|
||||||
|
serviceList.emplace_back(inputService);
|
||||||
return serviceList;
|
return serviceList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +138,17 @@ IService::Pointer ServiceFactory::createBluetoothService(aasdk::messenger::IMess
|
|||||||
return std::make_shared<BluetoothService>(ioService_, messenger, std::move(bluetoothDevice));
|
return std::make_shared<BluetoothService>(ioService_, messenger, std::move(bluetoothDevice));
|
||||||
}
|
}
|
||||||
|
|
||||||
IService::Pointer ServiceFactory::createInputService(aasdk::messenger::IMessenger::Pointer messenger)
|
std::shared_ptr<NavigationStatusService> ServiceFactory::createNavigationStatusService(aasdk::messenger::IMessenger::Pointer messenger)
|
||||||
|
{
|
||||||
|
return std::make_shared<NavigationStatusService>(ioService_, messenger, aa_interface_);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<MediaStatusService> ServiceFactory::createMediaStatusService(aasdk::messenger::IMessenger::Pointer messenger)
|
||||||
|
{
|
||||||
|
return std::make_shared<MediaStatusService>(ioService_, messenger, aa_interface_);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<InputService> ServiceFactory::createInputService(aasdk::messenger::IMessenger::Pointer messenger)
|
||||||
{
|
{
|
||||||
QRect videoGeometry;
|
QRect videoGeometry;
|
||||||
switch(configuration_->getVideoResolution())
|
switch(configuration_->getVideoResolution())
|
||||||
@ -145,6 +166,11 @@ IService::Pointer ServiceFactory::createInputService(aasdk::messenger::IMessenge
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//account for margins being applied to android auto
|
||||||
|
videoGeometry.setWidth(videoGeometry.width()-configuration_->getVideoMargins().width());
|
||||||
|
videoGeometry.setHeight(videoGeometry.height()-configuration_->getVideoMargins().height());
|
||||||
|
|
||||||
|
|
||||||
QObject* inputObject = activeArea_ == nullptr ? qobject_cast<QObject*>(QApplication::instance()) : qobject_cast<QObject*>(activeArea_);
|
QObject* inputObject = activeArea_ == nullptr ? qobject_cast<QObject*>(QApplication::instance()) : qobject_cast<QObject*>(activeArea_);
|
||||||
inputDevice_ = std::make_shared<projection::InputDevice>(*inputObject, configuration_, std::move(screenGeometry_), std::move(videoGeometry));
|
inputDevice_ = std::make_shared<projection::InputDevice>(*inputObject, configuration_, std::move(screenGeometry_), std::move(videoGeometry));
|
||||||
|
|
||||||
@ -212,6 +238,20 @@ void ServiceFactory::resize()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
void ServiceFactory::setAndroidAutoInterface(IAndroidAutoInterface* aa_interface){
|
||||||
|
if(aa_interface==NULL) return;
|
||||||
|
this->aa_interface_ = aa_interface;
|
||||||
|
|
||||||
|
if(std::shared_ptr<MediaStatusService> mediaStatusService = mediaStatusService_.lock())
|
||||||
|
{
|
||||||
|
mediaStatusService->setAndroidAutoInterface(aa_interface);
|
||||||
|
}
|
||||||
|
if(std::shared_ptr<NavigationStatusService> navStatusService = navStatusService_.lock())
|
||||||
|
{
|
||||||
|
navStatusService->setAndroidAutoInterface(aa_interface);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void ServiceFactory::setNightMode(bool nightMode)
|
void ServiceFactory::setNightMode(bool nightMode)
|
||||||
{
|
{
|
||||||
@ -222,6 +262,15 @@ void ServiceFactory::setNightMode(bool nightMode)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ServiceFactory::sendButtonPress(aasdk::proto::enums::ButtonCode::Enum buttonCode, projection::WheelDirection wheelDirection, projection::ButtonEventType buttonEventType)
|
||||||
|
{
|
||||||
|
if(std::shared_ptr<InputService> inputService = inputService_.lock())
|
||||||
|
{
|
||||||
|
|
||||||
|
inputService->sendButtonPress(buttonCode, wheelDirection, buttonEventType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ServiceFactory::sendKeyEvent(QKeyEvent* event)
|
void ServiceFactory::sendKeyEvent(QKeyEvent* event)
|
||||||
{
|
{
|
||||||
if(inputDevice_ != nullptr)
|
if(inputDevice_ != nullptr)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user