File indexing completed on 2024-04-28 16:42:53

0001 // SPDX-FileCopyrightText: 2012 George Kiagiadakis <kiagiadakis.george@gmail.com>
0002 // SPDX-FileCopyrightText: 2021 Alexey Andreyev <aa13q@ya.ru>
0003 //
0004 // SPDX-License-Identifier: LGPL-2.1-or-later
0005 
0006 #include "call-manager.h"
0007 
0008 #include <QCoreApplication>
0009 #include <QDBusConnection>
0010 #include <QDBusInterface>
0011 #include <QDBusReply>
0012 #include <QDebug>
0013 #include <QStringLiteral>
0014 
0015 #include "call-utils.h"
0016 #include "modem-controller.h"
0017 
0018 CallManager::CallManager(ModemController *modemController, CallUtils *callUtils, QObject *parent)
0019     : QObject(parent)
0020 {
0021     _modemController = modemController;
0022     _callUtils = callUtils;
0023 
0024     connect(_modemController, &ModemController::callStateChanged, this, &CallManager::onCallStateChanged);
0025     connect(_modemController, &ModemController::callAdded, this, &CallManager::onCallAdded);
0026     connect(_modemController, &ModemController::callDeleted, this, &CallManager::onCallDeleted);
0027 
0028     connect(_callUtils, &CallUtils::dialed, this, &CallManager::onUtilsCreatedCall);
0029     connect(_callUtils, &CallUtils::accepted, this, &CallManager::onUtilsAccepted);
0030     connect(_callUtils, &CallUtils::hungUp, this, &CallManager::onUtilsHungUp);
0031     connect(_callUtils, &CallUtils::sentDtmf, this, &CallManager::onUtilsSentDtmf);
0032 
0033     connect(_callUtils, &CallUtils::callsRequested, this, &CallManager::onUtilsCallsRequested);
0034 
0035     callUtils->fetchCalls();
0036 }
0037 
0038 void CallManager::onCallAdded(const QString &deviceUni,
0039                               const QString &callUni,
0040                               const DialerTypes::CallDirection &callDirection,
0041                               const DialerTypes::CallState &callState,
0042                               const DialerTypes::CallStateReason &callStateReason,
0043                               const QString communicationWith)
0044 {
0045     qDebug() << "call added:" << deviceUni << callUni;
0046     _callUtils->addCall(deviceUni, callUni, callDirection, callState, callStateReason, communicationWith);
0047 }
0048 
0049 void CallManager::onCallDeleted(const QString &deviceUni, const QString &callUni)
0050 {
0051     qDebug() << "call deleted:" << deviceUni << callUni;
0052     _callUtils->deleteCall(deviceUni, callUni);
0053 }
0054 
0055 void CallManager::onCallStateChanged(const DialerTypes::CallData &callData)
0056 {
0057     qDebug() << "new call state:" << callData.state << callData.stateReason;
0058     _callUtils->setCallState(callData);
0059 
0060     // Add inhibition in logind when call is active.
0061     // Otherwise if powerdevil is configured to suspend device afer few minutes,
0062     // it will happily put it to suspend, freezing calls.
0063     //
0064     // For XDG spec, see also:
0065     // https://gitlab.freedesktop.org/xdg/xdg-specs/-/issues/99
0066     //
0067     // For Solid support state, see also:
0068     // https://invent.kde.org/frameworks/solid/-/blob/79bdd41abcd479f486976596fcca40b388caa9b2/CMakeLists.txt#L97-L104
0069     switch (callData.state) {
0070     case DialerTypes::CallState::Active: {
0071         qDebug() << "logind sleep inhibitor: starting";
0072 
0073         if (_inhibitSleepFd) {
0074             qDebug() << "logind sleep inhibitor: already inhibited";
0075             break;
0076         }
0077 
0078         auto bus = QDBusConnection::systemBus();
0079 
0080         if (!bus.isConnected()) {
0081             qDebug() << "logind sleep inhibitor: error: D-Bus system bus is not connected";
0082             break;
0083         }
0084 
0085         QDBusMessage sleepInhibitCall = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.login1"),
0086                                                                        QStringLiteral("/org/freedesktop/login1"),
0087                                                                        QStringLiteral("org.freedesktop.login1.Manager"),
0088                                                                        QStringLiteral("Inhibit"));
0089         sleepInhibitCall.setArguments(
0090             {QStringLiteral("sleep"), QCoreApplication::instance()->applicationName(), tr("Active call inhibits system suspend"), QStringLiteral("block")});
0091         QDBusReply<QDBusUnixFileDescriptor> reply = bus.call(sleepInhibitCall);
0092 
0093         if (!reply.isValid()) {
0094             qDebug() << "logind sleep inhibitor: error: call failed";
0095             break;
0096         }
0097 
0098         auto const fd = reply.value();
0099         if (!fd.isValid()) {
0100             qDebug() << "logind sleep inhibitor: error: call returned an invalid file descriptor";
0101             break;
0102         }
0103         _inhibitSleepFd = fd;
0104         qDebug() << "logind sleep inhibitor: success";
0105         break;
0106     }
0107     case DialerTypes::CallState::Terminated: {
0108         QString deviceUni; // TODO: improve deviceUni getter
0109         _modemController->deleteCall(deviceUni, callData.id);
0110         _inhibitSleepFd.reset();
0111         qDebug() << "logind sleep inhibitor: turned off";
0112         break;
0113     }
0114     default:
0115         break;
0116     }
0117 }
0118 
0119 void CallManager::onUtilsCreatedCall(const QString &deviceUni, const QString &callUni)
0120 {
0121     _modemController->createCall(deviceUni, callUni);
0122 }
0123 
0124 void CallManager::onUtilsAccepted(const QString &deviceUni, const QString &callUni)
0125 {
0126     _modemController->acceptCall(deviceUni, callUni);
0127 }
0128 
0129 void CallManager::onUtilsHungUp(const QString &deviceUni, const QString &callUni)
0130 {
0131     _modemController->hangUp(deviceUni, callUni);
0132 }
0133 
0134 void CallManager::onUtilsSentDtmf(const QString &deviceUni, const QString &callUni, const QString &tones)
0135 {
0136     _modemController->sendDtmf(deviceUni, callUni, tones);
0137 }
0138 
0139 void CallManager::onUtilsCallsRequested()
0140 {
0141     _callUtils->setCalls(_modemController->fetchCalls());
0142 }