diff options
Diffstat (limited to 'AudioManagerPoC/business_logic/src')
4 files changed, 701 insertions, 0 deletions
diff --git a/AudioManagerPoC/business_logic/src/audioManagerInterface.cpp b/AudioManagerPoC/business_logic/src/audioManagerInterface.cpp new file mode 100644 index 0000000..90bbf37 --- /dev/null +++ b/AudioManagerPoC/business_logic/src/audioManagerInterface.cpp @@ -0,0 +1,230 @@ +/** + * SPDX license identifier: MPL-2.0 + * + * Copyright (C) 2011-2014, Wind River Systems + * Copyright (C) 2014, GENIVI Alliance + * + * This file is part of GENIVI AudioManager PoC. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License (MPL), v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * For further information see http://www.genivi.org/. + * + * List of changes: + * + * 21.09.2014, Adrian Scarlat, First version of the code; + * Added Copyright and License information; + */ + +#include <QtDBus> +#include <QDBusVariant> +#include <QVariant> + +#include "business_logic/include/audioManagerInterface.h" + + + +audioManagerInterface::audioManagerInterface(QObject *parent) : + QDBusAbstractInterface( + QString("org.genivi.audiomanager"), + QString("/org/genivi/audiomanager/commandinterface"), + "org.genivi.audiomanager.commandinterface", + QDBusConnection::sessionBus(), + parent) +{ + qDBusRegisterMetaType<MainConnection>(); + qDBusRegisterMetaType<Availability>(); + qDBusRegisterMetaType<Sink>(); + qDBusRegisterMetaType<Source>(); + + qDBusRegisterMetaType<QList<MainConnection> >(); + qDBusRegisterMetaType<QList<Availability> >(); + qDBusRegisterMetaType<QList<Sink> >(); + qDBusRegisterMetaType<QList<Source> >(); + + GetListMainSources(); + GetListMainSinks(); + GetListMainConnections(); + +} + +void audioManagerInterface::Connect(const QString sourceName, const QString sinkName) +{ + qDebug() <<"Connect got called: " << sourceName << " " << sinkName; + QDBusMessage result = this->call( + "Connect", + QVariant::fromValue((ushort) sourceName2SourceID[sourceName]), + QVariant::fromValue((ushort) sinkName2SinkID[sinkName])); + QVariant resultCode = result.arguments().at(0); + QVariant mainConnectionID = result.arguments().at(1); + qDebug() <<"Connection ID: " << mainConnectionID.toInt(); + + if (mainConnectionID.toUInt() != 0) // connection doesn't exist + { + mainConnectionID2SourceName[mainConnectionID.toUInt()] = sourceName; + sourceName2mainConnectionID[sourceName] = mainConnectionID.toUInt(); + } +} + +void audioManagerInterface::Disconnect(const QString sourceName, const QString sinkName) +{ + qDebug() <<"Disconnect got called: " << sourceName << " " << sinkName; + qDebug() <<"Disconnect got called Cond ID: " << sourceName2mainConnectionID[sourceName]; + QDBusMessage result = this->call( + "Disconnect", + QVariant::fromValue((ushort) sourceName2mainConnectionID[sourceName])); + QVariant resultCode = result.arguments().at(0); +} + +QList<Source> audioManagerInterface::GetListMainSources() +{ + QDBusMessage result = this->call("GetListMainSources"); + if (result.errorMessage() != "") + { + return QList<Source>(); + } + QList<Source> sources = qdbus_cast<QList<Source> >(result.arguments().at(1)); + for (int i = 0; i < sources.size(); i++) + { + + sourceName2SourceID[sources[i].name] = sources[i].sourceID; + } + return sources; +} + +QList<Sink> audioManagerInterface::GetListMainSinks() +{ + QDBusMessage result = this->call("GetListMainSinks"); + if (result.errorMessage() != "") + { + return QList<Sink>(); + } + QList<Sink> sinks = qdbus_cast<QList<Sink> >(result.arguments().at(1)); + for (int i = 0; i < sinks.size(); i++) + { + + sinkName2SinkID[sinks[i].name] = sinks[i].sinkID; + } + return sinks; +} + +QList<MainConnection> audioManagerInterface::GetListMainConnections() +{ + QDBusMessage result = this->call("GetListMainConnections"); + + if (result.errorMessage() != "") + { + return QList<MainConnection>(); + } + + QList<MainConnection> connections = qdbus_cast<QList<MainConnection> >(result.arguments().at(1)); + for (int i = 0; i < connections.size(); i++) + { + mainConnectionID2SourceName[connections[i].mainConnectionID] = connections[i].mainConnectionID; + } + + return connections; +} + +void audioManagerInterface::SetVolume(const QString sinkName, short volume) +{ + QDBusMessage result = this->call( + "SetVolume", + QVariant::fromValue((ushort) sinkName2SinkID[sinkName]), + QVariant::fromValue(volume)); + QVariant resultCode = result.arguments().at(0); +} + +QDBusArgument &operator<<(QDBusArgument &argument, const MainConnection &theStruct) +{ + argument.beginStructure(); + argument << theStruct.mainConnectionID + << theStruct.sourceID + << theStruct.sinkID + << theStruct.delay + << theStruct.connectionState; + argument.endStructure(); + return argument; +} + +const QDBusArgument &operator>>(const QDBusArgument &argument, MainConnection &theStruct) +{ + argument.beginStructure(); + argument >> theStruct.mainConnectionID + >> theStruct.sourceID + >> theStruct.sinkID + >> theStruct.delay + >> theStruct.connectionState; + argument.endStructure(); + return argument; +} + +QDBusArgument &operator<<(QDBusArgument &argument, const Availability &theStruct) +{ + argument.beginStructure(); + argument << theStruct.available + << theStruct.reason; + argument.endStructure(); + return argument; +} + +const QDBusArgument &operator>>(const QDBusArgument &argument, Availability &theStruct) +{ + argument.beginStructure(); + argument >> theStruct.available + >> theStruct.reason; + argument.endStructure(); + return argument; +} + +QDBusArgument &operator<<(QDBusArgument &argument, const Sink &theStruct) +{ + argument.beginStructure(); + argument << theStruct.sinkID + << theStruct.name + << theStruct.availability + << theStruct.volume + << theStruct.muteState + << theStruct.sinkClassID; + argument.endStructure(); + return argument; +} + +const QDBusArgument &operator>>(const QDBusArgument &argument, Sink &theStruct) +{ + argument.beginStructure(); + argument >> theStruct.sinkID + >> theStruct.name + >> theStruct.availability + >> theStruct.volume + >> theStruct.muteState + >> theStruct.sinkClassID; + argument.endStructure(); + return argument; +} + +QDBusArgument &operator<<(QDBusArgument &argument, const Source &theStruct) +{ + argument.beginStructure(); + argument << theStruct.sourceID + << theStruct.name + << theStruct.availability + << theStruct.sourceClassID + << theStruct.volume; + argument.endStructure(); + return argument; +} + +const QDBusArgument &operator>>(const QDBusArgument &argument, Source &theStruct) +{ + argument.beginStructure(); + argument >> theStruct.sourceID + >> theStruct.name + >> theStruct.availability + >> theStruct.sourceClassID + >> theStruct.volume; + argument.endStructure(); + return argument; +} diff --git a/AudioManagerPoC/business_logic/src/main.cpp b/AudioManagerPoC/business_logic/src/main.cpp new file mode 100644 index 0000000..3bdd518 --- /dev/null +++ b/AudioManagerPoC/business_logic/src/main.cpp @@ -0,0 +1,87 @@ +/** + * SPDX license identifier: MPL-2.0 + * + * Copyright (C) 2011-2014, Wind River Systems + * Copyright (C) 2014, GENIVI Alliance + * + * This file is part of GENIVI AudioManager PoC. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License (MPL), v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * For further information see http://www.genivi.org/. + * + * List of changes: + * + * 21.09.2014, Adrian Scarlat, First version of the code; + * Added Copyright and License information; + * + * 28.11.2014, Adrian Scarlat, Added code to allow only one instance of + * AM PoC to run; This was achieved by creating + * a file in /var/run and placing an advisory + * lock on it, using flock(). When another + * instance is created, it can't create the advisory + * lock on the same file since the first instance + * owns it and it will quit with an appropriate + * message. + */ + +#include <QApplication> +#include <QQuickView> +#include <QQmlContext> +#include <QDebug> +#include <QGraphicsObject> +#include <QTimer> +#include <QQmlEngine> +#include <QQuickItem> + +#include <sys/file.h> +#include <errno.h> + +#include "business_logic/include/qmlbuttoneventsreceiver.h" +#include "business_logic/include/volumechart.h" +#include "business_logic/include/audioManagerInterface.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + int pid_file = open("/var/run/AudioManager_PoC.pid", O_CREAT | O_RDWR, 0666); + if(pid_file != -1) + { + int rc = flock(pid_file, LOCK_EX | LOCK_NB); + if(rc) + { + if(EWOULDBLOCK == errno) + { + qDebug() << "Only one instance of AudioManager_PoC is allowed. Quitting!"; + return 0; + } + } + else + { + QQuickView view; + QMLButtonEventsReceiver rec(&view); + view.rootContext()->setContextProperty("QMLButtonEventsReceiver", &rec); + view.engine()->addImageProvider(QLatin1String("volumes"), new volumechart()); + view.setSource(QUrl("qrc:/presentation_layer/main.qml")); + view.showMaximized(); + + qDebug() << "Show maximized"; + + QTimer *timer = new QTimer(&rec); + QObject::connect(timer, SIGNAL(timeout()), &rec, SLOT(slotRefreshInfo())); + timer->start(500); + + QObject *sliderVolume = view.rootObject()->findChild<QObject*>("sliderVolume"); + sliderVolume->setProperty("value", 100.0); + + return app.exec(); + } + } + else + { + qDebug() << "Couldn't create /var/run/AudioManager_PoC.pid file."; + return 0; + } +} diff --git a/AudioManagerPoC/business_logic/src/qmlbuttoneventsreceiver.cpp b/AudioManagerPoC/business_logic/src/qmlbuttoneventsreceiver.cpp new file mode 100644 index 0000000..f6d95dc --- /dev/null +++ b/AudioManagerPoC/business_logic/src/qmlbuttoneventsreceiver.cpp @@ -0,0 +1,298 @@ +/** + * SPDX license identifier: MPL-2.0 + * + * Copyright (C) 2011-2014, Wind River Systems + * Copyright (C) 2014, GENIVI Alliance + * + * This file is part of GENIVI AudioManager PoC. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License (MPL), v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * For further information see http://www.genivi.org/. + * + * List of changes: + * + * 21.09.2014, Adrian Scarlat, First version of the code; + * Added Copyright and License information; + */ + +#include <QDebug> +#include <QProcess> +#include <QApplication> +#include <QQuickView> +#include <QQmlContext> +#include <QQuickItem> +#include <QDebug> +#include <QString> +#include <QStringList> +#include <QGraphicsObject> +#include <QFileDialog> +#include <QStringListModel> +#include <QThread> + +#include "business_logic/include/qmlbuttoneventsreceiver.h" +#include "business_logic/include/volumechart.h" + +/** + * The value for volume is in percentage and is relative to the PulseAudio + * volume. Consult PulseAudio documentaion for a description about how + * volume is measured inside PulseAudio. + */ +static int masterVolumeFG = 100; +static int masterVolumeBG = 100; +static audioManagerInterface *static_amgr; + +QMLButtonEventsReceiver::QMLButtonEventsReceiver(QQuickView *view) +{ + playMusic = "/opt/audiomanager-poc/scripts/playmusic.sh"; + stopMusic = "/opt/audiomanager-poc/scripts/stopmusic.sh"; + playCarReverse = "/opt/audiomanager-poc/scripts/playCarReverse.sh"; + stopCarReverse = "/opt/audiomanager-poc/scripts/stopCarReverse.sh"; + playNav = "/opt/audiomanager-poc/scripts/playnav.sh"; + stopNav = "/opt/audiomanager-poc/scripts/stopnav.sh"; + playTTS = "/opt/audiomanager-poc/scripts/playtts.sh"; + stopTTS = "/opt/audiomanager-poc/scripts/stoptts.sh"; + playTel = "/opt/audiomanager-poc/scripts/playtel.sh"; + stopTel = "/opt/audiomanager-poc/scripts/stoptel.sh"; + getConnections = "/opt/audiomanager-poc/scripts/getconnections.sh"; + getVolumes = "/opt/audiomanager-poc/scripts/getvolumes_val.sh"; + + this->amgr = new audioManagerInterface(view); + static_amgr = amgr; + this->view = view; + channel = BACKGROUND_CHANNEL; +} + +QString QMLButtonEventsReceiver::clicked(QString btnText) const +{ + qDebug() << "Clicked:" << btnText; + + if (btnText == "Play Music") { + amgr->Connect("MediaPlayer", "AlsaPrimary"); + QProcess *p1 = new QProcess(); + p1->start(playMusic); + connect(p1, SIGNAL(finished(int)), SLOT(slotMediaEnd())); + return "Stop Music"; + } + + if (btnText == "Stop Music") { + amgr->Disconnect("MediaPlayer", "AlsaPrimary"); + QProcess *p1 = new QProcess(); + p1->start(stopMusic); + return "Play Music"; + } + + if (btnText == "Parking Signal") { + amgr->Connect("ReverseBeep", "AlsaSecondary"); + QProcess *p1 = new QProcess(); + p1->start(playCarReverse); + connect(p1, SIGNAL(finished(int)), SLOT(slotCarEnd())); + return "Stop Parking Signal"; + } + + if (btnText == "Stop Parking Signal") { + amgr->Disconnect("ReverseBeep", "AlsaSecondary"); + QProcess *p1 = new QProcess(); + p1->start(stopCarReverse); + return "Parking Signal"; + } + + if (btnText == "Navigation Message") { + amgr->Connect("NaviPlayer", "AlsaSecondary"); + QProcess *p1 = new QProcess(); + p1->start(playNav); + connect(p1, SIGNAL(finished(int)), SLOT(slotNavEnd())); + return "Stop Navigation Message"; + } + + if (btnText == "Stop Navigation Message") { + amgr->Disconnect("NaviPlayer", "AlsaSecondary"); + QProcess *p1 = new QProcess(); + p1->start(stopNav); + return "Navigation Message"; + } + + if (btnText == "Text To Speech") { + amgr->Connect("TTSPlayer", "AlsaSecondary"); + QProcess *p1 = new QProcess(); + p1->start(playTTS); + connect(p1, SIGNAL(finished(int)), SLOT(slotTTSEnd())); + return "Stop Text To Speech"; + } + + if (btnText == "Stop Text To Speech") { + amgr->Disconnect("TTSPlayer", "AlsaSecondary"); + QProcess *p1 = new QProcess(); + p1->start(stopTTS); + return "Text To Speech"; + } + + if (btnText == "Start Phone Call") { + amgr->Connect("Skype", "AlsaSecondary"); + QProcess *p1 = new QProcess(); + p1->start(playTel); + connect(p1, SIGNAL(finished(int)), SLOT(slotTelEnd())); + return "End Phone Call"; + } + + if (btnText == "End Phone Call") { + amgr->Disconnect("Skype", "AlsaSecondary"); + QProcess *p1 = new QProcess(); + p1->start(stopTel); + return "Start Phone Call"; + } + + return btnText; +} + + +void QMLButtonEventsReceiver::slider(QString sliderText, qreal value) const +{ + if (sliderText == "Volume") + { + if (channel == FOREGROUND_CHANNEL) + { + masterVolumeFG = (int) value; + amgr->SetVolume("AlsaSecondary", value); + } + else + { + masterVolumeBG = (int) value; + amgr->SetVolume("AlsaPrimary", value); + } + } +} + +void QMLButtonEventsReceiver::slotRefreshInfo() +{ + QObject *text = view->rootObject()->findChild<QObject*>("textConnections"); + QObject *textSrc = view->rootObject()->findChild<QObject*>("textSources"); + QObject *textVol = view->rootObject()->findChild<QObject*>("textVolumes"); + + QProcess *p1 = new QProcess(); + p1->start(getConnections); + p1->waitForFinished(-1); + + QString p_stdout = p1->readAllStandardOutput(); + + text->setProperty("text", QString(p_stdout)); + QStringList linesConnections = QString(p_stdout).split("\n"); + + QProcess *p2 = new QProcess(); + p2->start(getVolumes); + p2->waitForFinished(-1); + + p_stdout = p2->readAllStandardOutput(); + + QStringList lines = QString(p_stdout).split("\n"); + QString audiosources = ""; + QString audiovolumes = ""; + + int oldChannel = channel; + + channel = BACKGROUND_CHANNEL; + QObject *channelTXT = view->rootObject()->findChild<QObject*>("channel"); + + for (int i = 0; i < lines.size(); i++) + { + QStringList x = lines[i].split(","); + if (x.length() == 2 && x.at(0).length() != 0 && x.at(1).length() != 0 ) + { + QString src = QString(x.at(0)); + QString vol = "0"; + audiosources += src + "\n"; + int masterVolume = masterVolumeBG; + for (int j = 0; j < linesConnections.size(); j++) + { + if (linesConnections[j].contains(src) && linesConnections[j].contains("Connected")) + { + vol = QString(x.at(1)); + if (linesConnections[j].contains("AlsaSecondary")) + { + channel = FOREGROUND_CHANNEL; + masterVolume = masterVolumeFG; + } + } + } + audiovolumes += vol + "\n"; + volumechart::volumes[i].push_back(masterVolume * vol.toInt() / 100); + } + } + + if (oldChannel != channel) + { + QObject *sliderVolume = view->rootObject()->findChild<QObject*>("sliderVolume"); + + if (channel == BACKGROUND_CHANNEL) + { + channelTXT->setProperty("text", "Background Channel"); + sliderVolume->setProperty("value", masterVolumeBG); + } + if (channel == FOREGROUND_CHANNEL) + { + channelTXT->setProperty("text", "Foreground Channel"); + sliderVolume->setProperty("value", masterVolumeFG); + } + } + + textSrc->setProperty("text", audiosources); + textVol->setProperty("text", audiovolumes); +} + +void QMLButtonEventsReceiver::slotMediaEnd() +{ + qDebug() << "slotMediaEnd"; + amgr->Disconnect("MediaPlayer", "AlsaPrimary"); + QProcess *p1 = new QProcess(); + p1->start(stopMusic); + + QObject *connectOptions = view->rootObject()->findChild<QObject*>("music"); + connectOptions->setProperty("text", "Play Music"); +} + +void QMLButtonEventsReceiver::slotCarEnd() +{ + qDebug() << "slotCarEnd"; + amgr->Disconnect("ReverseBeep", "AlsaSecondary"); + QProcess *p1 = new QProcess(); + p1->start(stopCarReverse); + + QObject *connectOptions = view->rootObject()->findChild<QObject*>("parking"); + connectOptions->setProperty("text", "Parking Signal"); +} + +void QMLButtonEventsReceiver::slotNavEnd() +{ + qDebug() << "slotNavEnd"; + amgr->Disconnect("NaviPlayer", "AlsaSecondary"); + QProcess *p1 = new QProcess(); + p1->start(stopNav); + + QObject *connectOptions = view->rootObject()->findChild<QObject*>("nav"); + connectOptions->setProperty("text", "Navigation Message"); +} + + +void QMLButtonEventsReceiver::slotTTSEnd() +{ + qDebug() << "slotTTSEnd"; + amgr->Disconnect("TTSPlayer", "AlsaSecondary"); + QProcess *p1 = new QProcess(); + p1->start(stopTTS); + + QObject *connectOptions = view->rootObject()->findChild<QObject*>("tts"); + connectOptions->setProperty("text", "Text To Speech"); +} + +void QMLButtonEventsReceiver::slotTelEnd() +{ + qDebug() << "slotTelEnd"; + amgr->Disconnect("Skype", "AlsaSecondary"); + QProcess *p1 = new QProcess(); + p1->start(stopTel); + + QObject *connectOptions = view->rootObject()->findChild<QObject*>("phone"); + connectOptions->setProperty("text", "Start Phone Call"); +} diff --git a/AudioManagerPoC/business_logic/src/volumechart.cpp b/AudioManagerPoC/business_logic/src/volumechart.cpp new file mode 100644 index 0000000..d8ecfbc --- /dev/null +++ b/AudioManagerPoC/business_logic/src/volumechart.cpp @@ -0,0 +1,86 @@ +/** + * SPDX license identifier: MPL-2.0 + * + * Copyright (C) 2011-2014, Wind River Systems + * Copyright (C) 2014, GENIVI Alliance + * + * This file is part of GENIVI AudioManager PoC. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License (MPL), v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * For further information see http://www.genivi.org/. + * + * List of changes: + * + * 21.09.2014, Adrian Scarlat, First version of the code; + * Added Copyright and License information; + */ + +#include <qqmlextensionplugin.h> +#include <QQmlEngine> +#include <QQuickItem> +#include <QQuickImageProvider> +#include <QQuickView> +#include <QImage> +#include <QPainter> +#include <QDebug> + +#include "business_logic/include/volumechart.h" + +QList<QList<int> > volumechart::volumes; + + +volumechart::volumechart() + : QQuickImageProvider(QQuickImageProvider::Pixmap) +{ + QList<int> l1; + volumechart::volumes.push_back(l1); + QList<int> l2; + volumechart::volumes.push_back(l2); + QList<int> l3; + volumechart::volumes.push_back(l3); + QList<int> l4; + volumechart::volumes.push_back(l4); + QList<int> l5; + volumechart::volumes.push_back(l5); +} + +QPixmap volumechart::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) +{ + int width = 400; + int height = 100; + + if (size) + *size = QSize(width, height); + QPixmap pixmap(requestedSize.width() > 0 ? requestedSize.width() : width, + requestedSize.height() > 0 ? requestedSize.height() : height); + pixmap.fill(QColor(0, 0, 0)); + + QPainter painter(&pixmap); + QColor colors[10]; + colors[0] = Qt::red; + colors[1] = Qt::green; + colors[2] = Qt::blue; + colors[3] = Qt::yellow; + colors[4] = Qt::cyan; + colors[5] = Qt::magenta; + colors[6] = Qt::darkCyan; + painter.setRenderHints(QPainter::Antialiasing); + for (int src = 0; src < volumes.size(); src++) + { + painter.setPen(colors[src]); + int limitMin = 1; + if (volumes[src].size() > 40) + { + limitMin = volumes[src].size() - 40; + } + for (int i = limitMin; i < volumes[src].size(); i++) + { + painter.drawLine((i - 1 - (limitMin -1)) * 10, src * 2 + 75 - volumes[src][i - 1] / 2, + (i - (limitMin -1)) * 10, src * 2 + 75 - volumes[src][i]/2); + } + } + return pixmap; +} |