File indexing completed on 2025-02-02 05:16:30

0001 // SPDX-FileCopyrightText: 2021 Alexey Andreyev <aa13q@ya.ru>
0002 //
0003 // SPDX-License-Identifier: LicenseRef-KDE-Accepted-GPL
0004 
0005 #pragma once
0006 
0007 #include <type_traits>
0008 
0009 #include <QDBusArgument>
0010 #include <QDBusMetaType>
0011 #include <QDateTime>
0012 #include <QObject>
0013 #include <QString>
0014 
0015 namespace DialerTypes
0016 {
0017 Q_NAMESPACE
0018 
0019 enum class CallState { Unknown, Dialing, RingingOut, RingingIn, Active, Held, Waiting, Terminated };
0020 
0021 enum class CallStateReason {
0022     Unknown,
0023     OutgoingStarted,
0024     IncomingNew,
0025     Accepted,
0026     TerminatedReason,
0027     RefusedOrBusy,
0028     Error,
0029     AudioSetupFailed,
0030     Transferred,
0031     Deflected
0032 };
0033 
0034 enum class CallDirection {
0035     Unknown,
0036     Incoming,
0037     Outgoing,
0038 };
0039 
0040 Q_ENUM_NS(CallState)
0041 Q_ENUM_NS(CallStateReason)
0042 Q_ENUM_NS(CallDirection)
0043 
0044 struct CallData {
0045     QString id; // event id
0046 
0047     QString protocol; // protocol id: tel, mtx, tg
0048     QString provider; // provider id: sim value displayed with sim name/icon or homeserver id)
0049     QString account; // account id: phone number or mtx id)
0050 
0051     QString communicationWith; // interlocutor: a phone number or room id
0052     DialerTypes::CallDirection direction; // direction (incoming/outgoing/unknown)
0053     DialerTypes::CallState state; // call state
0054     DialerTypes::CallStateReason stateReason; // call state reason
0055 
0056     int callAttemptDuration; // call attempt duration
0057     QDateTime startedAt; // started at
0058     int duration; // call duration
0059 };
0060 
0061 // Marshalling for CallState, CallStateReason and CallDirection enums:
0062 
0063 template<typename T, typename TEnum>
0064 struct QDBusEnumMarshal;
0065 
0066 template<typename T>
0067 struct QDBusEnumMarshal<T, std::true_type> {
0068     static QDBusArgument &marshal(QDBusArgument &argument, const T &source)
0069     {
0070         argument.beginStructure();
0071         argument << static_cast<int>(source);
0072         argument.endStructure();
0073         return argument;
0074     }
0075 
0076     static const QDBusArgument &unmarshal(const QDBusArgument &argument, T &source)
0077     {
0078         int a;
0079         argument.beginStructure();
0080         argument >> a;
0081         argument.endStructure();
0082 
0083         source = static_cast<T>(a);
0084         return argument;
0085     }
0086 };
0087 
0088 // Marshalling for CallData struct:
0089 
0090 template<typename T>
0091 struct QDBusCallDataMarshal;
0092 
0093 template<>
0094 struct QDBusCallDataMarshal<CallData> {
0095     static QDBusArgument &marshal(QDBusArgument &argument, const CallData &source)
0096     {
0097         QVariantMap dict;
0098         dict.insert(QStringLiteral("id"), source.id);
0099         dict.insert(QStringLiteral("protocol"), source.protocol);
0100         dict.insert(QStringLiteral("account"), source.account);
0101         dict.insert(QStringLiteral("provider"), source.provider);
0102         dict.insert(QStringLiteral("communicationWith"), source.communicationWith);
0103         dict.insert(QStringLiteral("direction"), static_cast<int>(source.direction));
0104         dict.insert(QStringLiteral("state"), static_cast<int>(source.state));
0105         dict.insert(QStringLiteral("stateReason"), static_cast<int>(source.stateReason));
0106         dict.insert(QStringLiteral("callAttemptDuration"), source.callAttemptDuration);
0107         dict.insert(QStringLiteral("startedAt"), source.startedAt.toSecsSinceEpoch());
0108         dict.insert(QStringLiteral("duration"), source.duration);
0109 
0110         argument.beginStructure();
0111         argument << dict;
0112         argument.endStructure();
0113         return argument;
0114     };
0115 
0116     static const QDBusArgument &unmarshal(const QDBusArgument &argument, CallData &source)
0117     {
0118         QVariantMap dict;
0119         argument.beginStructure();
0120         argument >> dict;
0121         argument.endStructure();
0122 
0123         source.id = dict.value(QStringLiteral("id")).toString();
0124         source.protocol = dict.value(QStringLiteral("protocol")).toString();
0125         source.account = dict.value(QStringLiteral("account")).toString();
0126         source.provider = dict.value(QStringLiteral("provider")).toString();
0127         source.communicationWith = dict.value(QStringLiteral("communicationWith")).toString();
0128 
0129         source.direction = dict.value(QStringLiteral("direction"), 0).value<DialerTypes::CallDirection>();
0130         source.state = dict.value(QStringLiteral("state"), 0).value<DialerTypes::CallState>();
0131         source.stateReason = dict.value(QStringLiteral("stateReason"), 0).value<DialerTypes::CallStateReason>();
0132 
0133         source.callAttemptDuration = dict.value(QStringLiteral("callAttemptDuration"), 0).toInt();
0134         source.startedAt = QDateTime::fromSecsSinceEpoch((uint)dict.value(QStringLiteral("startedAt"), 0).toLongLong());
0135         source.duration = dict.value(QStringLiteral("duration"), 0).toInt();
0136 
0137         return argument;
0138     };
0139 };
0140 
0141 template<typename T>
0142 QDBusArgument &operator<<(QDBusArgument &argument, const T &source)
0143 {
0144     if constexpr (std::is_same_v<T, CallData>) {
0145         return QDBusCallDataMarshal<CallData>::marshal(argument, source);
0146     } else {
0147         return QDBusEnumMarshal<T, typename std::is_enum<T>::type>::marshal(argument, source);
0148     }
0149 }
0150 
0151 template<typename T>
0152 const QDBusArgument &operator>>(const QDBusArgument &argument, T &source)
0153 {
0154     if constexpr (std::is_same_v<T, CallData>) {
0155         return QDBusCallDataMarshal<CallData>::unmarshal(argument, source);
0156     } else {
0157         return QDBusEnumMarshal<T, typename std::is_enum<T>::type>::unmarshal(argument, source);
0158     };
0159 }
0160 
0161 using CallDataVector = QVector<DialerTypes::CallData>;
0162 
0163 } // namespace DialerTypes
0164 
0165 Q_DECLARE_METATYPE(DialerTypes::CallState)
0166 Q_DECLARE_METATYPE(DialerTypes::CallStateReason)
0167 Q_DECLARE_METATYPE(DialerTypes::CallDirection)
0168 Q_DECLARE_METATYPE(DialerTypes::CallData)
0169 Q_DECLARE_METATYPE(DialerTypes::CallDataVector)
0170 
0171 namespace DialerTypes
0172 {
0173 inline void registerMetaTypes()
0174 {
0175     qRegisterMetaType<DialerTypes::CallState>("DialerTypesCallState");
0176     qDBusRegisterMetaType<DialerTypes::CallState>();
0177 
0178     qRegisterMetaType<DialerTypes::CallStateReason>("DialerTypesCallStateReason");
0179     qDBusRegisterMetaType<DialerTypes::CallStateReason>();
0180 
0181     qRegisterMetaType<DialerTypes::CallDirection>("DialerTypesCallDirection");
0182     qDBusRegisterMetaType<DialerTypes::CallDirection>();
0183 
0184     qRegisterMetaType<DialerTypes::CallData>("DialerTypesCallData");
0185     qDBusRegisterMetaType<DialerTypes::CallData>();
0186 
0187     qRegisterMetaType<DialerTypes::CallDataVector>("DialerTypesCallDataVector");
0188     qDBusRegisterMetaType<DialerTypes::CallDataVector>();
0189 }
0190 }