7b1f10d4d5
## Summary Add support for Phone side (like in the Android and SailfishOS apps) to telephony plugin. this requires ModemManager to work. Call state notifications are currently supported, more capabilities are possible. Tested on PinePhone but should probably work on every linux Phone with ModemManager. to test, pair kdeconnect on your linux phone to desktop, and call your phone. you should get notification on the desktop, telling you that phone call is incoming.
135 lines
4.5 KiB
C++
135 lines
4.5 KiB
C++
/**
|
|
* SPDX-FileCopyrightText: 2019 Richard Liebscher <richard.liebscher@gmail.com>
|
|
* SPDX-FileCopyrightText: 2022 Yoram Bar Haim <bhyoram@protonmail.com>
|
|
*
|
|
* SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-KDE-Accepted-GPL
|
|
*/
|
|
|
|
#include "mmtelephonyplugin.h"
|
|
|
|
#include <KLocalizedString>
|
|
#include <QDebug>
|
|
#include <QLoggingCategory>
|
|
|
|
#include "plugin_mmtelephony_debug.h"
|
|
#include <KPluginFactory>
|
|
|
|
K_PLUGIN_CLASS_WITH_JSON(MMTelephonyPlugin, "kdeconnect_mmtelephony.json")
|
|
|
|
static const QString PACKET_TYPE_TELEPHONY = QStringLiteral("kdeconnect.telephony");
|
|
static const QString PACKET_TYPE_TELEPHONY_REQUEST_MUTE = QStringLiteral("kdeconnect.telephony.request_mute");
|
|
|
|
QSharedPointer<ModemManager::ModemVoice> _voiceInterface(const QSharedPointer<ModemManager::ModemDevice> modemDevice)
|
|
{
|
|
return modemDevice->interface(ModemManager::ModemDevice::VoiceInterface).objectCast<ModemManager::ModemVoice>();
|
|
}
|
|
|
|
MMTelephonyPlugin::MMTelephonyPlugin(QObject *parent, const QVariantList &args)
|
|
: KdeConnectPlugin(parent, args)
|
|
{
|
|
connect(ModemManager::notifier(), &ModemManager::Notifier::modemAdded, this, &MMTelephonyPlugin::onModemAdded);
|
|
}
|
|
|
|
bool MMTelephonyPlugin::receivePacket(const NetworkPacket &np)
|
|
{
|
|
if (np.get<QString>(QStringLiteral("event")) == QLatin1String("mute")) {
|
|
// TODO: mute code
|
|
return true;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void MMTelephonyPlugin::onModemAdded(const QString &path)
|
|
{
|
|
auto modemDevice = ModemManager::findModemDevice(path);
|
|
QSharedPointer<ModemManager::ModemVoice> vcm = _voiceInterface(modemDevice);
|
|
auto voice = vcm.get();
|
|
connect(voice, &ModemManager::ModemVoice::callAdded, this, [this, voice](const QString &uni) {
|
|
auto call = voice->findCall(uni);
|
|
onCallAdded(call);
|
|
});
|
|
connect(voice, &ModemManager::ModemVoice::callDeleted, this, [this, voice](const QString &uni) {
|
|
auto call = voice->findCall(uni);
|
|
onCallRemoved(call);
|
|
});
|
|
}
|
|
|
|
void MMTelephonyPlugin::onModemRemoved(const QString &path)
|
|
{
|
|
Q_UNUSED(path);
|
|
}
|
|
|
|
void MMTelephonyPlugin::onCallAdded(ModemManager::Call::Ptr call)
|
|
{
|
|
qCDebug(KDECONNECT_PLUGIN_MMTELEPHONY) << "Call added" << call->number();
|
|
|
|
connect(call.get(), &ModemManager::Call::stateChanged, this, [=](MMCallState newState, MMCallState oldState, MMCallStateReason reason) {
|
|
onCallStateChanged(call.get(), newState, oldState, reason);
|
|
});
|
|
}
|
|
|
|
void MMTelephonyPlugin::onCallRemoved(ModemManager::Call::Ptr call)
|
|
{
|
|
qCDebug(KDECONNECT_PLUGIN_MMTELEPHONY) << "Call removed" << call.get()->number();
|
|
}
|
|
|
|
QString MMTelephonyPlugin::stateName(MMCallState state)
|
|
{
|
|
QString event;
|
|
switch (state) {
|
|
case MMCallState::MM_CALL_STATE_RINGING_IN:
|
|
event = QStringLiteral("ringing");
|
|
break;
|
|
case MMCallState::MM_CALL_STATE_ACTIVE:
|
|
event = QStringLiteral("talking");
|
|
break;
|
|
case MMCallState::MM_CALL_STATE_TERMINATED:
|
|
event = QStringLiteral("disconnected");
|
|
break;
|
|
case MMCallState::MM_CALL_STATE_UNKNOWN:
|
|
default:
|
|
event = QStringLiteral("Unknown");
|
|
}
|
|
return event;
|
|
}
|
|
|
|
void MMTelephonyPlugin::onCallStateChanged(ModemManager::Call *call, MMCallState newState, MMCallState oldState, MMCallStateReason reason)
|
|
{
|
|
Q_UNUSED(reason);
|
|
auto event = stateName(newState);
|
|
|
|
qCDebug(KDECONNECT_PLUGIN_MMTELEPHONY) << "Call state changed" << call->uni() << event;
|
|
if (newState != MMCallState::MM_CALL_STATE_TERMINATED)
|
|
sendMMTelephonyPacket(call, event);
|
|
else
|
|
sendCancelMMTelephonyPacket(call, stateName(oldState));
|
|
}
|
|
|
|
void MMTelephonyPlugin::sendMMTelephonyPacket(ModemManager::Call *call, const QString &state)
|
|
{
|
|
QString phoneNumber = call->number();
|
|
|
|
qCDebug(KDECONNECT_PLUGIN_MMTELEPHONY) << "Phone number is" << phoneNumber;
|
|
NetworkPacket np{PACKET_TYPE_TELEPHONY,
|
|
{
|
|
{QStringLiteral("event"), state},
|
|
{QStringLiteral("phoneNumber"), phoneNumber},
|
|
{QStringLiteral("contactName"), phoneNumber},
|
|
}};
|
|
sendPacket(np);
|
|
}
|
|
|
|
void MMTelephonyPlugin::sendCancelMMTelephonyPacket(ModemManager::Call *call, const QString &lastState)
|
|
{
|
|
QString phoneNumber = call->number();
|
|
|
|
NetworkPacket np{PACKET_TYPE_TELEPHONY,
|
|
{{QStringLiteral("event"), lastState},
|
|
{QStringLiteral("phoneNumber"), phoneNumber},
|
|
{QStringLiteral("contactName"), phoneNumber},
|
|
{QStringLiteral("isCancel"), true}}};
|
|
sendPacket(np);
|
|
}
|
|
|
|
#include "mmtelephonyplugin.moc"
|