mirror of
https://github.com/kavishdevar/librepods.git
synced 2026-01-28 22:01:50 +00:00
[Linux] Move all device related properties to new class (#135)
* Clean up code * Move all device releated properties to new class
This commit is contained in:
@@ -18,22 +18,12 @@ namespace ControlCommand
|
|||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse activated/not activated
|
inline std::optional<char> parseActive(const QByteArray &data)
|
||||||
inline std::optional<bool> parseActive(const QByteArray &data)
|
|
||||||
{
|
{
|
||||||
if (!data.startsWith(ControlCommand::HEADER))
|
if (!data.startsWith(ControlCommand::HEADER))
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
quint8 statusByte = static_cast<quint8>(data.at(7));
|
return static_cast<quint8>(data.at(7));
|
||||||
switch (statusByte)
|
|
||||||
{
|
|
||||||
case 0x01: // Enabled
|
|
||||||
return true;
|
|
||||||
case 0x02: // Disabled
|
|
||||||
return false;
|
|
||||||
default:
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,6 +44,19 @@ struct BasicControlCommand
|
|||||||
|
|
||||||
// Basically returns the byte at the index 7
|
// Basically returns the byte at the index 7
|
||||||
static std::optional<bool> parseState(const QByteArray &data)
|
static std::optional<bool> parseState(const QByteArray &data)
|
||||||
|
{
|
||||||
|
switch (ControlCommand::parseActive(data).value_or(0x00))
|
||||||
|
{
|
||||||
|
case 0x01: // Enabled
|
||||||
|
return true;
|
||||||
|
case 0x02: // Disabled
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::optional<char> getValue(const QByteArray &data)
|
||||||
{
|
{
|
||||||
return ControlCommand::parseActive(data);
|
return ControlCommand::parseActive(data);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ qt_add_executable(applinux
|
|||||||
BluetoothMonitor.h
|
BluetoothMonitor.h
|
||||||
autostartmanager.hpp
|
autostartmanager.hpp
|
||||||
BasicControlCommand.hpp
|
BasicControlCommand.hpp
|
||||||
|
deviceinfo.hpp
|
||||||
)
|
)
|
||||||
|
|
||||||
qt_add_qml_module(applinux
|
qt_add_qml_module(applinux
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ namespace AirPodsPackets
|
|||||||
// Noise Control Mode Packets
|
// Noise Control Mode Packets
|
||||||
namespace NoiseControl
|
namespace NoiseControl
|
||||||
{
|
{
|
||||||
|
using NoiseControlMode = AirpodsTrayApp::Enums::NoiseControlMode;
|
||||||
static const QByteArray HEADER = ControlCommand::HEADER + 0x0D;
|
static const QByteArray HEADER = ControlCommand::HEADER + 0x0D;
|
||||||
static const QByteArray OFF = ControlCommand::createCommand(0x0D, 0x01);
|
static const QByteArray OFF = ControlCommand::createCommand(0x0D, 0x01);
|
||||||
static const QByteArray NOISE_CANCELLATION = ControlCommand::createCommand(0x0D, 0x02);
|
static const QByteArray NOISE_CANCELLATION = ControlCommand::createCommand(0x0D, 0x02);
|
||||||
@@ -21,7 +22,6 @@ namespace AirPodsPackets
|
|||||||
|
|
||||||
static const QByteArray getPacketForMode(AirpodsTrayApp::Enums::NoiseControlMode mode)
|
static const QByteArray getPacketForMode(AirpodsTrayApp::Enums::NoiseControlMode mode)
|
||||||
{
|
{
|
||||||
using NoiseControlMode = AirpodsTrayApp::Enums::NoiseControlMode;
|
|
||||||
switch (mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
case NoiseControlMode::Off:
|
case NoiseControlMode::Off:
|
||||||
@@ -36,6 +36,17 @@ namespace AirPodsPackets
|
|||||||
return QByteArray();
|
return QByteArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline std::optional<NoiseControlMode> parseMode(const QByteArray &data)
|
||||||
|
{
|
||||||
|
char mode = ControlCommand::parseActive(data).value_or(CHAR_MAX);
|
||||||
|
if (mode < static_cast<quint8>(NoiseControlMode::MinValue) ||
|
||||||
|
mode > static_cast<quint8>(NoiseControlMode::MaxValue))
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
return static_cast<NoiseControlMode>(mode - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// One Bud ANC Mode
|
// One Bud ANC Mode
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|||||||
209
linux/deviceinfo.hpp
Normal file
209
linux/deviceinfo.hpp
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QByteArray>
|
||||||
|
#include "battery.hpp"
|
||||||
|
#include "enums.h"
|
||||||
|
|
||||||
|
using namespace AirpodsTrayApp::Enums;
|
||||||
|
|
||||||
|
class DeviceInfo : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QString batteryStatus READ batteryStatus WRITE setBatteryStatus NOTIFY batteryStatusChanged)
|
||||||
|
Q_PROPERTY(QString earDetectionStatus READ earDetectionStatus WRITE setEarDetectionStatus NOTIFY earDetectionStatusChanged)
|
||||||
|
Q_PROPERTY(int noiseControlMode READ noiseControlModeInt WRITE setNoiseControlModeInt NOTIFY noiseControlModeChangedInt)
|
||||||
|
Q_PROPERTY(bool conversationalAwareness READ conversationalAwareness WRITE setConversationalAwareness NOTIFY conversationalAwarenessChanged)
|
||||||
|
Q_PROPERTY(int adaptiveNoiseLevel READ adaptiveNoiseLevel WRITE setAdaptiveNoiseLevel NOTIFY adaptiveNoiseLevelChanged)
|
||||||
|
Q_PROPERTY(QString deviceName READ deviceName WRITE setDeviceName NOTIFY deviceNameChanged)
|
||||||
|
Q_PROPERTY(Battery *battery READ getBattery CONSTANT)
|
||||||
|
Q_PROPERTY(bool primaryInEar READ isPrimaryInEar WRITE setPrimaryInEar NOTIFY primaryChanged)
|
||||||
|
Q_PROPERTY(bool secondaryInEar READ isSecondaryInEar WRITE setSecondaryInEar NOTIFY primaryChanged)
|
||||||
|
Q_PROPERTY(bool oneBudANCMode READ oneBudANCMode WRITE setOneBudANCMode NOTIFY oneBudANCModeChanged)
|
||||||
|
Q_PROPERTY(AirPodsModel model READ model WRITE setModel NOTIFY modelChanged)
|
||||||
|
Q_PROPERTY(bool adaptiveModeActive READ adaptiveModeActive NOTIFY noiseControlModeChangedInt)
|
||||||
|
Q_PROPERTY(QString podIcon READ podIcon NOTIFY modelChanged)
|
||||||
|
Q_PROPERTY(QString caseIcon READ caseIcon NOTIFY modelChanged)
|
||||||
|
Q_PROPERTY(bool leftPodInEar READ isLeftPodInEar NOTIFY primaryChanged)
|
||||||
|
Q_PROPERTY(bool rightPodInEar READ isRightPodInEar NOTIFY primaryChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit DeviceInfo(QObject *parent = nullptr) : QObject(parent), m_battery(new Battery(this)) {}
|
||||||
|
|
||||||
|
QString batteryStatus() const { return m_batteryStatus; }
|
||||||
|
void setBatteryStatus(const QString &status)
|
||||||
|
{
|
||||||
|
if (m_batteryStatus != status)
|
||||||
|
{
|
||||||
|
m_batteryStatus = status;
|
||||||
|
emit batteryStatusChanged(status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString earDetectionStatus() const { return m_earDetectionStatus; }
|
||||||
|
void setEarDetectionStatus(const QString &status)
|
||||||
|
{
|
||||||
|
if (m_earDetectionStatus != status)
|
||||||
|
{
|
||||||
|
m_earDetectionStatus = status;
|
||||||
|
emit earDetectionStatusChanged(status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NoiseControlMode noiseControlMode() const { return m_noiseControlMode; }
|
||||||
|
void setNoiseControlMode(NoiseControlMode mode)
|
||||||
|
{
|
||||||
|
if (m_noiseControlMode != mode)
|
||||||
|
{
|
||||||
|
m_noiseControlMode = mode;
|
||||||
|
emit noiseControlModeChanged(mode);
|
||||||
|
emit noiseControlModeChangedInt(static_cast<int>(mode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int noiseControlModeInt() const { return static_cast<int>(noiseControlMode()); }
|
||||||
|
void setNoiseControlModeInt(int mode) { setNoiseControlMode(static_cast<NoiseControlMode>(mode)); }
|
||||||
|
|
||||||
|
bool conversationalAwareness() const { return m_conversationalAwareness; }
|
||||||
|
void setConversationalAwareness(bool enabled)
|
||||||
|
{
|
||||||
|
if (m_conversationalAwareness != enabled)
|
||||||
|
{
|
||||||
|
m_conversationalAwareness = enabled;
|
||||||
|
emit conversationalAwarenessChanged(enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int adaptiveNoiseLevel() const { return m_adaptiveNoiseLevel; }
|
||||||
|
void setAdaptiveNoiseLevel(int level)
|
||||||
|
{
|
||||||
|
if (m_adaptiveNoiseLevel != level)
|
||||||
|
{
|
||||||
|
m_adaptiveNoiseLevel = level;
|
||||||
|
emit adaptiveNoiseLevelChanged(level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString deviceName() const { return m_deviceName; }
|
||||||
|
void setDeviceName(const QString &name)
|
||||||
|
{
|
||||||
|
if (m_deviceName != name)
|
||||||
|
{
|
||||||
|
m_deviceName = name;
|
||||||
|
emit deviceNameChanged(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Battery *getBattery() const { return m_battery; }
|
||||||
|
|
||||||
|
bool isPrimaryInEar() const { return m_primaryInEar; }
|
||||||
|
void setPrimaryInEar(bool inEar)
|
||||||
|
{
|
||||||
|
if (m_primaryInEar != inEar)
|
||||||
|
{
|
||||||
|
m_primaryInEar = inEar;
|
||||||
|
emit primaryChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isSecondaryInEar() const { return m_secoundaryInEar; }
|
||||||
|
void setSecondaryInEar(bool inEar)
|
||||||
|
{
|
||||||
|
if (m_secoundaryInEar != inEar)
|
||||||
|
{
|
||||||
|
m_secoundaryInEar = inEar;
|
||||||
|
emit primaryChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool oneBudANCMode() const { return m_oneBudANCMode; }
|
||||||
|
void setOneBudANCMode(bool enabled)
|
||||||
|
{
|
||||||
|
if (m_oneBudANCMode != enabled)
|
||||||
|
{
|
||||||
|
m_oneBudANCMode = enabled;
|
||||||
|
emit oneBudANCModeChanged(enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AirPodsModel model() const { return m_model; }
|
||||||
|
void setModel(AirPodsModel model)
|
||||||
|
{
|
||||||
|
if (m_model != model)
|
||||||
|
{
|
||||||
|
m_model = model;
|
||||||
|
emit modelChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray magicAccIRK() const { return m_magicAccIRK; }
|
||||||
|
void setMagicAccIRK(const QByteArray &irk) { m_magicAccIRK = irk; }
|
||||||
|
|
||||||
|
QByteArray magicAccEncKey() const { return m_magicAccEncKey; }
|
||||||
|
void setMagicAccEncKey(const QByteArray &key) { m_magicAccEncKey = key; }
|
||||||
|
|
||||||
|
QString modelNumber() const { return m_modelNumber; }
|
||||||
|
void setModelNumber(const QString &modelNumber) { m_modelNumber = modelNumber; }
|
||||||
|
|
||||||
|
QString manufacturer() const { return m_manufacturer; }
|
||||||
|
void setManufacturer(const QString &manufacturer) { m_manufacturer = manufacturer; }
|
||||||
|
|
||||||
|
QString podIcon() const { return getModelIcon(model()).first; }
|
||||||
|
QString caseIcon() const { return getModelIcon(model()).second; }
|
||||||
|
bool isLeftPodInEar() const
|
||||||
|
{
|
||||||
|
if (getBattery()->getPrimaryPod() == Battery::Component::Left) return isPrimaryInEar();
|
||||||
|
else return isSecondaryInEar();
|
||||||
|
}
|
||||||
|
bool isRightPodInEar() const
|
||||||
|
{
|
||||||
|
if (getBattery()->getPrimaryPod() == Battery::Component::Right) return isPrimaryInEar();
|
||||||
|
else return isSecondaryInEar();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool adaptiveModeActive() const { return noiseControlMode() == NoiseControlMode::Adaptive; }
|
||||||
|
bool oneOrMorePodsInCase() const { return earDetectionStatus().contains("In case"); }
|
||||||
|
bool oneOrMorePodsInEar() const { return isPrimaryInEar() || isSecondaryInEar(); }
|
||||||
|
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
setDeviceName("");
|
||||||
|
setModel(AirPodsModel::Unknown);
|
||||||
|
m_battery->reset();
|
||||||
|
setBatteryStatus("");
|
||||||
|
setEarDetectionStatus("");
|
||||||
|
setPrimaryInEar(false);
|
||||||
|
setSecondaryInEar(false);
|
||||||
|
setNoiseControlMode(NoiseControlMode::Off);
|
||||||
|
}
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void batteryStatusChanged(const QString &status);
|
||||||
|
void earDetectionStatusChanged(const QString &status);
|
||||||
|
void noiseControlModeChanged(NoiseControlMode mode);
|
||||||
|
void noiseControlModeChangedInt(int mode);
|
||||||
|
void conversationalAwarenessChanged(bool enabled);
|
||||||
|
void adaptiveNoiseLevelChanged(int level);
|
||||||
|
void deviceNameChanged(const QString &name);
|
||||||
|
void primaryChanged();
|
||||||
|
void oneBudANCModeChanged(bool enabled);
|
||||||
|
void modelChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_batteryStatus;
|
||||||
|
QString m_earDetectionStatus;
|
||||||
|
NoiseControlMode m_noiseControlMode = NoiseControlMode::Off;
|
||||||
|
bool m_conversationalAwareness = false;
|
||||||
|
int m_adaptiveNoiseLevel = 50;
|
||||||
|
QString m_deviceName;
|
||||||
|
Battery *m_battery;
|
||||||
|
bool m_primaryInEar = false;
|
||||||
|
bool m_secoundaryInEar = false;
|
||||||
|
QByteArray m_magicAccIRK;
|
||||||
|
QByteArray m_magicAccEncKey;
|
||||||
|
bool m_oneBudANCMode = false;
|
||||||
|
AirPodsModel m_model = AirPodsModel::Unknown;
|
||||||
|
|
||||||
|
// Additional metadata fields
|
||||||
|
QString m_modelNumber;
|
||||||
|
QString m_manufacturer;
|
||||||
|
};
|
||||||
261
linux/main.cpp
261
linux/main.cpp
@@ -10,6 +10,7 @@
|
|||||||
#include "battery.hpp"
|
#include "battery.hpp"
|
||||||
#include "BluetoothMonitor.h"
|
#include "BluetoothMonitor.h"
|
||||||
#include "autostartmanager.hpp"
|
#include "autostartmanager.hpp"
|
||||||
|
#include "deviceinfo.hpp"
|
||||||
|
|
||||||
using namespace AirpodsTrayApp::Enums;
|
using namespace AirpodsTrayApp::Enums;
|
||||||
|
|
||||||
@@ -17,19 +18,6 @@ Q_LOGGING_CATEGORY(airpodsApp, "airpodsApp")
|
|||||||
|
|
||||||
class AirPodsTrayApp : public QObject {
|
class AirPodsTrayApp : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(QString batteryStatus READ batteryStatus NOTIFY batteryStatusChanged)
|
|
||||||
Q_PROPERTY(QString earDetectionStatus READ earDetectionStatus NOTIFY earDetectionStatusChanged)
|
|
||||||
Q_PROPERTY(int noiseControlMode READ noiseControlMode WRITE setNoiseControlMode NOTIFY noiseControlModeChanged)
|
|
||||||
Q_PROPERTY(bool conversationalAwareness READ conversationalAwareness WRITE setConversationalAwareness NOTIFY conversationalAwarenessChanged)
|
|
||||||
Q_PROPERTY(int adaptiveNoiseLevel READ adaptiveNoiseLevel WRITE setAdaptiveNoiseLevel NOTIFY adaptiveNoiseLevelChanged)
|
|
||||||
Q_PROPERTY(bool adaptiveModeActive READ adaptiveModeActive NOTIFY noiseControlModeChanged)
|
|
||||||
Q_PROPERTY(QString deviceName READ deviceName NOTIFY deviceNameChanged)
|
|
||||||
Q_PROPERTY(Battery* battery READ getBattery NOTIFY batteryStatusChanged)
|
|
||||||
Q_PROPERTY(bool oneOrMorePodsInCase READ oneOrMorePodsInCase NOTIFY earDetectionStatusChanged)
|
|
||||||
Q_PROPERTY(QString podIcon READ podIcon NOTIFY modelChanged)
|
|
||||||
Q_PROPERTY(QString caseIcon READ caseIcon NOTIFY modelChanged)
|
|
||||||
Q_PROPERTY(bool leftPodInEar READ isLeftPodInEar NOTIFY primaryChanged)
|
|
||||||
Q_PROPERTY(bool rightPodInEar READ isRightPodInEar NOTIFY primaryChanged)
|
|
||||||
Q_PROPERTY(bool airpodsConnected READ areAirpodsConnected NOTIFY airPodsStatusChanged)
|
Q_PROPERTY(bool airpodsConnected READ areAirpodsConnected NOTIFY airPodsStatusChanged)
|
||||||
Q_PROPERTY(int earDetectionBehavior READ earDetectionBehavior WRITE setEarDetectionBehavior NOTIFY earDetectionBehaviorChanged)
|
Q_PROPERTY(int earDetectionBehavior READ earDetectionBehavior WRITE setEarDetectionBehavior NOTIFY earDetectionBehaviorChanged)
|
||||||
Q_PROPERTY(bool crossDeviceEnabled READ crossDeviceEnabled WRITE setCrossDeviceEnabled NOTIFY crossDeviceEnabledChanged)
|
Q_PROPERTY(bool crossDeviceEnabled READ crossDeviceEnabled WRITE setCrossDeviceEnabled NOTIFY crossDeviceEnabledChanged)
|
||||||
@@ -37,24 +25,13 @@ class AirPodsTrayApp : public QObject {
|
|||||||
Q_PROPERTY(bool notificationsEnabled READ notificationsEnabled WRITE setNotificationsEnabled NOTIFY notificationsEnabledChanged)
|
Q_PROPERTY(bool notificationsEnabled READ notificationsEnabled WRITE setNotificationsEnabled NOTIFY notificationsEnabledChanged)
|
||||||
Q_PROPERTY(int retryAttempts READ retryAttempts WRITE setRetryAttempts NOTIFY retryAttemptsChanged)
|
Q_PROPERTY(int retryAttempts READ retryAttempts WRITE setRetryAttempts NOTIFY retryAttemptsChanged)
|
||||||
Q_PROPERTY(bool hideOnStart READ hideOnStart CONSTANT)
|
Q_PROPERTY(bool hideOnStart READ hideOnStart CONSTANT)
|
||||||
Q_PROPERTY(bool oneBudANCMode READ oneBudANCMode WRITE setOneBudANCMode NOTIFY oneBudANCModeChanged)
|
Q_PROPERTY(DeviceInfo *deviceInfo READ deviceInfo CONSTANT)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AirPodsTrayApp(bool debugMode, bool hideOnStart, QQmlApplicationEngine *parent = nullptr)
|
AirPodsTrayApp(bool debugMode, bool hideOnStart, QQmlApplicationEngine *parent = nullptr)
|
||||||
: QObject(parent)
|
: QObject(parent), debugMode(debugMode), m_settings(new QSettings("AirPodsTrayApp", "AirPodsTrayApp")), m_autoStartManager(new AutoStartManager(this)), m_hideOnStart(hideOnStart), parent(parent), m_deviceInfo(new DeviceInfo(this))
|
||||||
, debugMode(debugMode)
|
|
||||||
, m_battery(new Battery(this))
|
|
||||||
, monitor(new BluetoothMonitor(this))
|
|
||||||
, m_settings(new QSettings("AirPodsTrayApp", "AirPodsTrayApp"))
|
|
||||||
, m_autoStartManager(new AutoStartManager(this))
|
|
||||||
, m_hideOnStart(hideOnStart)
|
|
||||||
, parent(parent)
|
|
||||||
{
|
{
|
||||||
if (debugMode) {
|
QLoggingCategory::setFilterRules(QString("airpodsApp.debug=%1").arg(debugMode ? "true" : "false"));
|
||||||
QLoggingCategory::setFilterRules("airpodsApp.debug=true");
|
|
||||||
} else {
|
|
||||||
QLoggingCategory::setFilterRules("airpodsApp.debug=false");
|
|
||||||
}
|
|
||||||
LOG_INFO("Initializing AirPodsTrayApp");
|
LOG_INFO("Initializing AirPodsTrayApp");
|
||||||
|
|
||||||
// Initialize tray icon and connect signals
|
// Initialize tray icon and connect signals
|
||||||
@@ -63,25 +40,26 @@ public:
|
|||||||
connect(trayManager, &TrayIconManager::trayClicked, this, &AirPodsTrayApp::onTrayIconActivated);
|
connect(trayManager, &TrayIconManager::trayClicked, this, &AirPodsTrayApp::onTrayIconActivated);
|
||||||
connect(trayManager, &TrayIconManager::openApp, this, &AirPodsTrayApp::onOpenApp);
|
connect(trayManager, &TrayIconManager::openApp, this, &AirPodsTrayApp::onOpenApp);
|
||||||
connect(trayManager, &TrayIconManager::openSettings, this, &AirPodsTrayApp::onOpenSettings);
|
connect(trayManager, &TrayIconManager::openSettings, this, &AirPodsTrayApp::onOpenSettings);
|
||||||
connect(trayManager, &TrayIconManager::noiseControlChanged, this, qOverload<NoiseControlMode>(&AirPodsTrayApp::setNoiseControlMode));
|
connect(trayManager, &TrayIconManager::noiseControlChanged, this, &AirPodsTrayApp::setNoiseControlMode);
|
||||||
connect(trayManager, &TrayIconManager::conversationalAwarenessToggled, this, &AirPodsTrayApp::setConversationalAwareness);
|
connect(trayManager, &TrayIconManager::conversationalAwarenessToggled, this, &AirPodsTrayApp::setConversationalAwareness);
|
||||||
connect(this, &AirPodsTrayApp::batteryStatusChanged, trayManager, &TrayIconManager::updateBatteryStatus);
|
connect(m_deviceInfo, &DeviceInfo::batteryStatusChanged, trayManager, &TrayIconManager::updateBatteryStatus);
|
||||||
connect(this, &AirPodsTrayApp::noiseControlModeChanged, trayManager, &TrayIconManager::updateNoiseControlState);
|
connect(m_deviceInfo, &DeviceInfo::noiseControlModeChanged, trayManager, &TrayIconManager::updateNoiseControlState);
|
||||||
connect(this, &AirPodsTrayApp::conversationalAwarenessChanged, trayManager, &TrayIconManager::updateConversationalAwareness);
|
connect(m_deviceInfo, &DeviceInfo::conversationalAwarenessChanged, trayManager, &TrayIconManager::updateConversationalAwareness);
|
||||||
connect(trayManager, &TrayIconManager::notificationsEnabledChanged, this, &AirPodsTrayApp::saveNotificationsEnabled);
|
connect(trayManager, &TrayIconManager::notificationsEnabledChanged, this, &AirPodsTrayApp::saveNotificationsEnabled);
|
||||||
connect(trayManager, &TrayIconManager::notificationsEnabledChanged, this, &AirPodsTrayApp::notificationsEnabledChanged);
|
connect(trayManager, &TrayIconManager::notificationsEnabledChanged, this, &AirPodsTrayApp::notificationsEnabledChanged);
|
||||||
|
|
||||||
// Initialize MediaController and connect signals
|
// Initialize MediaController and connect signals
|
||||||
mediaController = new MediaController(this);
|
mediaController = new MediaController(this);
|
||||||
connect(this, &AirPodsTrayApp::earDetectionStatusChanged, mediaController, &MediaController::handleEarDetection);
|
connect(m_deviceInfo, &DeviceInfo::earDetectionStatusChanged, mediaController, &MediaController::handleEarDetection);
|
||||||
connect(mediaController, &MediaController::mediaStateChanged, this, &AirPodsTrayApp::handleMediaStateChange);
|
connect(mediaController, &MediaController::mediaStateChanged, this, &AirPodsTrayApp::handleMediaStateChange);
|
||||||
mediaController->initializeMprisInterface();
|
mediaController->initializeMprisInterface();
|
||||||
mediaController->followMediaChanges();
|
mediaController->followMediaChanges();
|
||||||
|
|
||||||
|
monitor = new BluetoothMonitor(this);
|
||||||
connect(monitor, &BluetoothMonitor::deviceConnected, this, &AirPodsTrayApp::bluezDeviceConnected);
|
connect(monitor, &BluetoothMonitor::deviceConnected, this, &AirPodsTrayApp::bluezDeviceConnected);
|
||||||
connect(monitor, &BluetoothMonitor::deviceDisconnected, this, &AirPodsTrayApp::bluezDeviceDisconnected);
|
connect(monitor, &BluetoothMonitor::deviceDisconnected, this, &AirPodsTrayApp::bluezDeviceDisconnected);
|
||||||
|
|
||||||
connect(m_battery, &Battery::primaryChanged, this, &AirPodsTrayApp::primaryChanged);
|
connect(m_deviceInfo->getBattery(), &Battery::primaryChanged, this, &AirPodsTrayApp::primaryChanged);
|
||||||
|
|
||||||
// Load settings
|
// Load settings
|
||||||
CrossDevice.isEnabled = loadCrossDeviceEnabled();
|
CrossDevice.isEnabled = loadCrossDeviceEnabled();
|
||||||
@@ -114,31 +92,6 @@ public:
|
|||||||
delete phoneSocket;
|
delete phoneSocket;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString batteryStatus() const { return m_batteryStatus; }
|
|
||||||
QString earDetectionStatus() const { return m_earDetectionStatus; }
|
|
||||||
int noiseControlMode() const { return static_cast<int>(m_noiseControlMode); }
|
|
||||||
bool conversationalAwareness() const { return m_conversationalAwareness; }
|
|
||||||
bool adaptiveModeActive() const { return m_noiseControlMode == NoiseControlMode::Adaptive; }
|
|
||||||
int adaptiveNoiseLevel() const { return m_adaptiveNoiseLevel; }
|
|
||||||
QString deviceName() const { return m_deviceName; }
|
|
||||||
Battery *getBattery() const { return m_battery; }
|
|
||||||
bool oneOrMorePodsInCase() const { return m_earDetectionStatus.contains("In case"); }
|
|
||||||
QString podIcon() const { return getModelIcon(m_model).first; }
|
|
||||||
QString caseIcon() const { return getModelIcon(m_model).second; }
|
|
||||||
bool isLeftPodInEar() const {
|
|
||||||
if (m_battery->getPrimaryPod() == Battery::Component::Left) {
|
|
||||||
return m_primaryInEar;
|
|
||||||
} else {
|
|
||||||
return m_secoundaryInEar;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool isRightPodInEar() const {
|
|
||||||
if (m_battery->getPrimaryPod() == Battery::Component::Right) {
|
|
||||||
return m_primaryInEar;
|
|
||||||
} else {
|
|
||||||
return m_secoundaryInEar;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool areAirpodsConnected() const { return socket && socket->isOpen() && socket->state() == QBluetoothSocket::SocketState::ConnectedState; }
|
bool areAirpodsConnected() const { return socket && socket->isOpen() && socket->state() == QBluetoothSocket::SocketState::ConnectedState; }
|
||||||
int earDetectionBehavior() const { return mediaController->getEarDetectionBehavior(); }
|
int earDetectionBehavior() const { return mediaController->getEarDetectionBehavior(); }
|
||||||
bool crossDeviceEnabled() const { return CrossDevice.isEnabled; }
|
bool crossDeviceEnabled() const { return CrossDevice.isEnabled; }
|
||||||
@@ -147,7 +100,7 @@ public:
|
|||||||
void setNotificationsEnabled(bool enabled) { trayManager->setNotificationsEnabled(enabled); }
|
void setNotificationsEnabled(bool enabled) { trayManager->setNotificationsEnabled(enabled); }
|
||||||
int retryAttempts() const { return m_retryAttempts; }
|
int retryAttempts() const { return m_retryAttempts; }
|
||||||
bool hideOnStart() const { return m_hideOnStart; }
|
bool hideOnStart() const { return m_hideOnStart; }
|
||||||
bool oneBudANCMode() const { return m_oneBudANCMode; }
|
DeviceInfo *deviceInfo() const { return m_deviceInfo; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool debugMode;
|
bool debugMode;
|
||||||
@@ -199,39 +152,32 @@ public slots:
|
|||||||
void setNoiseControlMode(NoiseControlMode mode)
|
void setNoiseControlMode(NoiseControlMode mode)
|
||||||
{
|
{
|
||||||
LOG_INFO("Setting noise control mode to: " << mode);
|
LOG_INFO("Setting noise control mode to: " << mode);
|
||||||
if (m_noiseControlMode == mode)
|
|
||||||
{
|
|
||||||
LOG_INFO("Noise control mode is already " << mode);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
QByteArray packet = AirPodsPackets::NoiseControl::getPacketForMode(mode);
|
QByteArray packet = AirPodsPackets::NoiseControl::getPacketForMode(mode);
|
||||||
writePacketToSocket(packet, "Noise control mode packet written: ");
|
writePacketToSocket(packet, "Noise control mode packet written: ");
|
||||||
}
|
}
|
||||||
void setNoiseControlMode(int mode)
|
void setNoiseControlModeInt(int mode)
|
||||||
{
|
{
|
||||||
|
if (mode < 0 || mode > static_cast<int>(NoiseControlMode::Adaptive))
|
||||||
|
{
|
||||||
|
LOG_ERROR("Invalid noise control mode: " << mode);
|
||||||
|
return;
|
||||||
|
}
|
||||||
setNoiseControlMode(static_cast<NoiseControlMode>(mode));
|
setNoiseControlMode(static_cast<NoiseControlMode>(mode));
|
||||||
}
|
}
|
||||||
|
|
||||||
void setConversationalAwareness(bool enabled)
|
void setConversationalAwareness(bool enabled)
|
||||||
{
|
{
|
||||||
if (m_conversationalAwareness == enabled)
|
|
||||||
{
|
|
||||||
LOG_INFO("Conversational awareness is already " << (enabled ? "enabled" : "disabled"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_INFO("Setting conversational awareness to: " << (enabled ? "enabled" : "disabled"));
|
LOG_INFO("Setting conversational awareness to: " << (enabled ? "enabled" : "disabled"));
|
||||||
QByteArray packet = enabled ? AirPodsPackets::ConversationalAwareness::ENABLED
|
QByteArray packet = enabled ? AirPodsPackets::ConversationalAwareness::ENABLED
|
||||||
: AirPodsPackets::ConversationalAwareness::DISABLED;
|
: AirPodsPackets::ConversationalAwareness::DISABLED;
|
||||||
|
|
||||||
writePacketToSocket(packet, "Conversational awareness packet written: ");
|
writePacketToSocket(packet, "Conversational awareness packet written: ");
|
||||||
m_conversationalAwareness = enabled;
|
m_deviceInfo->setConversationalAwareness(enabled);
|
||||||
emit conversationalAwarenessChanged(enabled);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setOneBudANCMode(bool enabled)
|
void setOneBudANCMode(bool enabled)
|
||||||
{
|
{
|
||||||
if (m_oneBudANCMode == enabled)
|
if (m_deviceInfo->oneBudANCMode() == enabled)
|
||||||
{
|
{
|
||||||
LOG_INFO("One Bud ANC mode is already " << (enabled ? "enabled" : "disabled"));
|
LOG_INFO("One Bud ANC mode is already " << (enabled ? "enabled" : "disabled"));
|
||||||
return;
|
return;
|
||||||
@@ -243,8 +189,7 @@ public slots:
|
|||||||
|
|
||||||
if (writePacketToSocket(packet, "One Bud ANC mode packet written: "))
|
if (writePacketToSocket(packet, "One Bud ANC mode packet written: "))
|
||||||
{
|
{
|
||||||
m_oneBudANCMode = enabled;
|
m_deviceInfo->setOneBudANCMode(enabled);
|
||||||
emit oneBudANCModeChanged(enabled);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -277,12 +222,11 @@ public slots:
|
|||||||
void setAdaptiveNoiseLevel(int level)
|
void setAdaptiveNoiseLevel(int level)
|
||||||
{
|
{
|
||||||
level = qBound(0, level, 100);
|
level = qBound(0, level, 100);
|
||||||
if (m_adaptiveNoiseLevel != level && adaptiveModeActive())
|
if (m_deviceInfo->adaptiveNoiseLevel() != level && m_deviceInfo->adaptiveModeActive())
|
||||||
{
|
{
|
||||||
m_adaptiveNoiseLevel = level;
|
|
||||||
QByteArray packet = AirPodsPackets::AdaptiveNoise::getPacket(level);
|
QByteArray packet = AirPodsPackets::AdaptiveNoise::getPacket(level);
|
||||||
writePacketToSocket(packet, "Adaptive noise level packet written: ");
|
writePacketToSocket(packet, "Adaptive noise level packet written: ");
|
||||||
emit adaptiveNoiseLevelChanged(level);
|
m_deviceInfo->setAdaptiveNoiseLevel(level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,7 +242,7 @@ public slots:
|
|||||||
LOG_WARN("Name is too long, must be 32 characters or less");
|
LOG_WARN("Name is too long, must be 32 characters or less");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (newName == m_deviceName)
|
if (newName == m_deviceInfo->deviceName())
|
||||||
{
|
{
|
||||||
LOG_INFO("Name is already set to: " << newName);
|
LOG_INFO("Name is already set to: " << newName);
|
||||||
return;
|
return;
|
||||||
@@ -308,8 +252,7 @@ public slots:
|
|||||||
if (writePacketToSocket(packet, "Rename packet written: "))
|
if (writePacketToSocket(packet, "Rename packet written: "))
|
||||||
{
|
{
|
||||||
LOG_INFO("Sent rename command for new name: " << newName);
|
LOG_INFO("Sent rename command for new name: " << newName);
|
||||||
m_deviceName = newName;
|
m_deviceInfo->setDeviceName(newName);
|
||||||
emit deviceNameChanged(newName);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -435,31 +378,7 @@ private slots:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Clear the device name and model
|
// Clear the device name and model
|
||||||
m_deviceName.clear();
|
m_deviceInfo->reset();
|
||||||
connectedDeviceMacAddress.clear();
|
|
||||||
mediaController->setConnectedDeviceMacAddress(connectedDeviceMacAddress);
|
|
||||||
m_model = AirPodsModel::Unknown;
|
|
||||||
emit deviceNameChanged(m_deviceName);
|
|
||||||
emit modelChanged();
|
|
||||||
|
|
||||||
// Reset battery status
|
|
||||||
m_battery->reset();
|
|
||||||
m_batteryStatus.clear();
|
|
||||||
emit batteryStatusChanged(m_batteryStatus);
|
|
||||||
|
|
||||||
// Reset ear detection
|
|
||||||
m_earDetectionStatus.clear();
|
|
||||||
m_primaryInEar = false;
|
|
||||||
m_secoundaryInEar = false;
|
|
||||||
emit earDetectionStatusChanged(m_earDetectionStatus);
|
|
||||||
emit primaryChanged();
|
|
||||||
|
|
||||||
// Reset noise control mode
|
|
||||||
m_noiseControlMode = NoiseControlMode::Off;
|
|
||||||
emit noiseControlModeChanged(m_noiseControlMode);
|
|
||||||
|
|
||||||
mediaController->pause(); // Since the device is deconnected, we don't know if it was the active output device. Pause to be safe
|
|
||||||
emit airPodsStatusChanged();
|
|
||||||
|
|
||||||
// Show system notification
|
// Show system notification
|
||||||
trayManager->showNotification(
|
trayManager->showNotification(
|
||||||
@@ -516,43 +435,18 @@ private slots:
|
|||||||
return str;
|
return str;
|
||||||
};
|
};
|
||||||
|
|
||||||
m_deviceName = extractString();
|
m_deviceInfo->setDeviceName(extractString());
|
||||||
QString modelNumber = extractString();
|
m_deviceInfo->setModelNumber(extractString());
|
||||||
QString manufacturer = extractString();
|
m_deviceInfo->setManufacturer(extractString());
|
||||||
QString hardwareVersion = extractString();
|
|
||||||
QString firmwareVersion = extractString();
|
|
||||||
QString firmwareVersion2 = extractString();
|
|
||||||
QString softwareVersion = extractString();
|
|
||||||
QString appIdentifier = extractString();
|
|
||||||
QString serialNumber1 = extractString();
|
|
||||||
QString serialNumber2 = extractString();
|
|
||||||
QString unknownNumeric = extractString();
|
|
||||||
QString unknownHash = extractString();
|
|
||||||
QString trailingByte = extractString();
|
|
||||||
|
|
||||||
m_model = parseModelNumber(modelNumber);
|
|
||||||
|
|
||||||
|
m_deviceInfo->setModel(parseModelNumber(m_deviceInfo->modelNumber()));
|
||||||
emit modelChanged();
|
emit modelChanged();
|
||||||
m_model = parseModelNumber(modelNumber);
|
|
||||||
|
|
||||||
emit modelChanged();
|
|
||||||
emit deviceNameChanged(m_deviceName);
|
|
||||||
|
|
||||||
// Log extracted metadata
|
// Log extracted metadata
|
||||||
LOG_INFO("Parsed AirPods metadata:");
|
LOG_INFO("Parsed AirPods metadata:");
|
||||||
LOG_INFO("Device Name: " << m_deviceName);
|
LOG_INFO("Device Name: " << m_deviceInfo->deviceName());
|
||||||
LOG_INFO("Model Number: " << modelNumber);
|
LOG_INFO("Model Number: " << m_deviceInfo->modelNumber());
|
||||||
LOG_INFO("Manufacturer: " << manufacturer);
|
LOG_INFO("Manufacturer: " << m_deviceInfo->manufacturer());
|
||||||
LOG_INFO("Hardware Version: " << hardwareVersion);
|
|
||||||
LOG_INFO("Firmware Version: " << firmwareVersion);
|
|
||||||
LOG_INFO("Firmware Version2: " << firmwareVersion2);
|
|
||||||
LOG_INFO("Software Version: " << softwareVersion);
|
|
||||||
LOG_INFO("App Identifier: " << appIdentifier);
|
|
||||||
LOG_INFO("Serial Number 1: " << serialNumber1);
|
|
||||||
LOG_INFO("Serial Number 2: " << serialNumber2);
|
|
||||||
LOG_INFO("Unknown Numeric: " << unknownNumeric);
|
|
||||||
LOG_INFO("Unknown Hash: " << unknownHash);
|
|
||||||
LOG_INFO("Trailing Byte: " << trailingByte);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString getEarStatus(char value)
|
QString getEarStatus(char value)
|
||||||
@@ -635,7 +529,7 @@ private slots:
|
|||||||
writePacketToSocket(AirPodsPackets::Connection::REQUEST_NOTIFICATIONS, "Request notifications packet written: ");
|
writePacketToSocket(AirPodsPackets::Connection::REQUEST_NOTIFICATIONS, "Request notifications packet written: ");
|
||||||
|
|
||||||
QTimer::singleShot(2000, this, [this]() {
|
QTimer::singleShot(2000, this, [this]() {
|
||||||
if (m_batteryStatus.isEmpty()) {
|
if (m_deviceInfo->batteryStatus().isEmpty()) {
|
||||||
writePacketToSocket(AirPodsPackets::Connection::REQUEST_NOTIFICATIONS, "Request notifications packet written: ");
|
writePacketToSocket(AirPodsPackets::Connection::REQUEST_NOTIFICATIONS, "Request notifications packet written: ");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -648,34 +542,26 @@ private slots:
|
|||||||
LOG_INFO("MagicAccIRK: " << keys.magicAccIRK.toHex());
|
LOG_INFO("MagicAccIRK: " << keys.magicAccIRK.toHex());
|
||||||
LOG_INFO("MagicAccEncKey: " << keys.magicAccEncKey.toHex());
|
LOG_INFO("MagicAccEncKey: " << keys.magicAccEncKey.toHex());
|
||||||
|
|
||||||
// Store the keys for later use if needed
|
// Store the keys
|
||||||
m_magicAccIRK = keys.magicAccIRK;
|
m_deviceInfo->setMagicAccIRK(keys.magicAccIRK);
|
||||||
m_magicAccEncKey = keys.magicAccEncKey;
|
m_deviceInfo->setMagicAccEncKey(keys.magicAccEncKey);
|
||||||
}
|
}
|
||||||
// Get CA state
|
// Get CA state
|
||||||
else if (data.startsWith(AirPodsPackets::ConversationalAwareness::HEADER)) {
|
else if (data.startsWith(AirPodsPackets::ConversationalAwareness::HEADER)) {
|
||||||
auto result = AirPodsPackets::ConversationalAwareness::parseState(data);
|
if (auto result = AirPodsPackets::ConversationalAwareness::parseState(data))
|
||||||
if (result.has_value()) {
|
{
|
||||||
m_conversationalAwareness = result.value();
|
m_deviceInfo->setConversationalAwareness(result.value());
|
||||||
LOG_INFO("Conversational awareness state received: " << m_conversationalAwareness);
|
LOG_INFO("Conversational awareness state received: " << m_deviceInfo->conversationalAwareness());
|
||||||
emit conversationalAwarenessChanged(m_conversationalAwareness);
|
|
||||||
} else {
|
|
||||||
LOG_ERROR("Failed to parse conversational awareness state");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Noise Control Mode
|
// Noise Control Mode
|
||||||
else if (data.size() == 11 && data.startsWith(AirPodsPackets::NoiseControl::HEADER))
|
else if (data.size() == 11 && data.startsWith(AirPodsPackets::NoiseControl::HEADER))
|
||||||
{
|
{
|
||||||
quint8 rawMode = data[7] - 1; // Offset still needed due to protocol
|
if (auto value = AirPodsPackets::NoiseControl::parseMode(data))
|
||||||
if (rawMode >= (int)NoiseControlMode::MinValue && rawMode <= (int)NoiseControlMode::MaxValue)
|
|
||||||
{
|
{
|
||||||
m_noiseControlMode = static_cast<NoiseControlMode>(rawMode);
|
LOG_INFO("Received noise control mode: " << value.value());
|
||||||
LOG_INFO("Noise control mode: " << rawMode);
|
m_deviceInfo->setNoiseControlMode(value.value());
|
||||||
emit noiseControlModeChanged(m_noiseControlMode);
|
LOG_INFO("Noise control mode received: " << m_deviceInfo->noiseControlMode());
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_ERROR("Invalid noise control mode value received: " << rawMode);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Ear Detection
|
// Ear Detection
|
||||||
@@ -683,28 +569,25 @@ private slots:
|
|||||||
{
|
{
|
||||||
char primary = data[6];
|
char primary = data[6];
|
||||||
char secondary = data[7];
|
char secondary = data[7];
|
||||||
m_primaryInEar = data[6] == 0x00;
|
m_deviceInfo->setPrimaryInEar(data[6] == 0x00);
|
||||||
m_secoundaryInEar = data[7] == 0x00;
|
m_deviceInfo->setSecondaryInEar(data[7] == 0x00);
|
||||||
m_earDetectionStatus = QString("Primary: %1, Secondary: %2")
|
m_deviceInfo->setEarDetectionStatus(QString("Primary: %1, Secondary: %2")
|
||||||
.arg(getEarStatus(primary), getEarStatus(secondary));
|
.arg(getEarStatus(primary), getEarStatus(secondary)));
|
||||||
LOG_INFO("Ear detection status: " << m_earDetectionStatus);
|
LOG_INFO("Ear detection status: " << m_deviceInfo->earDetectionStatus());
|
||||||
emit earDetectionStatusChanged(m_earDetectionStatus);
|
|
||||||
emit primaryChanged();
|
|
||||||
}
|
}
|
||||||
// Battery Status
|
// Battery Status
|
||||||
else if (data.size() == 22 && data.startsWith(AirPodsPackets::Parse::BATTERY_STATUS))
|
else if (data.size() == 22 && data.startsWith(AirPodsPackets::Parse::BATTERY_STATUS))
|
||||||
{
|
{
|
||||||
m_battery->parsePacket(data);
|
m_deviceInfo->getBattery()->parsePacket(data);
|
||||||
|
|
||||||
int leftLevel = m_battery->getState(Battery::Component::Left).level;
|
int leftLevel = m_deviceInfo->getBattery()->getState(Battery::Component::Left).level;
|
||||||
int rightLevel = m_battery->getState(Battery::Component::Right).level;
|
int rightLevel = m_deviceInfo->getBattery()->getState(Battery::Component::Right).level;
|
||||||
int caseLevel = m_battery->getState(Battery::Component::Case).level;
|
int caseLevel = m_deviceInfo->getBattery()->getState(Battery::Component::Case).level;
|
||||||
m_batteryStatus = QString("Left: %1%, Right: %2%, Case: %3%")
|
m_deviceInfo->setBatteryStatus(QString("Left: %1%, Right: %2%, Case: %3%")
|
||||||
.arg(leftLevel)
|
.arg(leftLevel)
|
||||||
.arg(rightLevel)
|
.arg(rightLevel)
|
||||||
.arg(caseLevel);
|
.arg(caseLevel));
|
||||||
LOG_INFO("Battery status: " << m_batteryStatus);
|
LOG_INFO("Battery status: " << m_deviceInfo->batteryStatus());
|
||||||
emit batteryStatusChanged(m_batteryStatus);
|
|
||||||
}
|
}
|
||||||
// Conversational Awareness Data
|
// Conversational Awareness Data
|
||||||
else if (data.size() == 10 && data.startsWith(AirPodsPackets::ConversationalAwareness::DATA_HEADER))
|
else if (data.size() == 10 && data.startsWith(AirPodsPackets::ConversationalAwareness::DATA_HEADER))
|
||||||
@@ -717,23 +600,17 @@ private slots:
|
|||||||
parseMetadata(data);
|
parseMetadata(data);
|
||||||
initiateMagicPairing();
|
initiateMagicPairing();
|
||||||
mediaController->setConnectedDeviceMacAddress(connectedDeviceMacAddress);
|
mediaController->setConnectedDeviceMacAddress(connectedDeviceMacAddress);
|
||||||
if (isLeftPodInEar() || isRightPodInEar()) // AirPods get added as output device only after this
|
if (m_deviceInfo->oneOrMorePodsInEar()) // AirPods get added as output device only after this
|
||||||
{
|
{
|
||||||
mediaController->activateA2dpProfile();
|
mediaController->activateA2dpProfile();
|
||||||
}
|
}
|
||||||
emit airPodsStatusChanged();
|
emit airPodsStatusChanged();
|
||||||
}
|
}
|
||||||
else if (data.startsWith(AirPodsPackets::OneBudANCMode::HEADER)) {
|
else if (data.startsWith(AirPodsPackets::OneBudANCMode::HEADER)) {
|
||||||
auto result = AirPodsPackets::OneBudANCMode::parseState(data);
|
if (auto value = AirPodsPackets::OneBudANCMode::parseState(data))
|
||||||
if (result.has_value())
|
|
||||||
{
|
{
|
||||||
m_oneBudANCMode = result.value();
|
m_deviceInfo->setOneBudANCMode(value.value());
|
||||||
LOG_INFO("One Bud ANC mode received: " << m_conversationalAwareness);
|
LOG_INFO("One Bud ANC mode received: " << m_deviceInfo->oneBudANCMode());
|
||||||
emit oneBudANCModeChanged(m_conversationalAwareness);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_ERROR("Failed to parse One Bud ANC mode");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -980,20 +857,7 @@ private:
|
|||||||
AutoStartManager *m_autoStartManager;
|
AutoStartManager *m_autoStartManager;
|
||||||
int m_retryAttempts = 3;
|
int m_retryAttempts = 3;
|
||||||
bool m_hideOnStart = false;
|
bool m_hideOnStart = false;
|
||||||
|
DeviceInfo *m_deviceInfo;
|
||||||
QString m_batteryStatus;
|
|
||||||
QString m_earDetectionStatus;
|
|
||||||
NoiseControlMode m_noiseControlMode = NoiseControlMode::Off;
|
|
||||||
bool m_conversationalAwareness = false;
|
|
||||||
int m_adaptiveNoiseLevel = 50;
|
|
||||||
QString m_deviceName;
|
|
||||||
Battery *m_battery;
|
|
||||||
AirPodsModel m_model = AirPodsModel::Unknown;
|
|
||||||
bool m_primaryInEar = false;
|
|
||||||
bool m_secoundaryInEar = false;
|
|
||||||
QByteArray m_magicAccIRK;
|
|
||||||
QByteArray m_magicAccEncKey;
|
|
||||||
bool m_oneBudANCMode = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
@@ -1038,6 +902,7 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
QQmlApplicationEngine engine;
|
QQmlApplicationEngine engine;
|
||||||
qmlRegisterType<Battery>("me.kavishdevar.Battery", 1, 0, "Battery");
|
qmlRegisterType<Battery>("me.kavishdevar.Battery", 1, 0, "Battery");
|
||||||
|
qmlRegisterType<DeviceInfo>("me.kavishdevar.DeviceInfo", 1, 0, "DeviceInfo");
|
||||||
AirPodsTrayApp *trayApp = new AirPodsTrayApp(debugMode, hideOnStart, &engine);
|
AirPodsTrayApp *trayApp = new AirPodsTrayApp(debugMode, hideOnStart, &engine);
|
||||||
engine.rootContext()->setContextProperty("airPodsTrayApp", trayApp);
|
engine.rootContext()->setContextProperty("airPodsTrayApp", trayApp);
|
||||||
trayApp->loadMainModule();
|
trayApp->loadMainModule();
|
||||||
|
|||||||
Reference in New Issue
Block a user