mirror of
https://github.com/kavishdevar/librepods.git
synced 2026-04-28 09:07:14 +00:00
linux: improve disconnection behaviour (#97)
Merge pull request #97 from tim-gromeyer/linux-disconnect-behaviour
This commit is contained in:
@@ -21,11 +21,17 @@ class Battery : public QObject
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Battery(QObject *parent = nullptr) : QObject(parent)
|
explicit Battery(QObject *parent = nullptr) : QObject(parent)
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset()
|
||||||
{
|
{
|
||||||
// Initialize all components to unknown state
|
// Initialize all components to unknown state
|
||||||
states[Component::Left] = {};
|
states[Component::Left] = {};
|
||||||
states[Component::Right] = {};
|
states[Component::Right] = {};
|
||||||
states[Component::Case] = {};
|
states[Component::Case] = {};
|
||||||
|
emit batteryStatusChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enum for AirPods components
|
// Enum for AirPods components
|
||||||
|
|||||||
@@ -359,18 +359,48 @@ private slots:
|
|||||||
LOG_WARN("Socket is still open, closing it");
|
LOG_WARN("Socket is still open, closing it");
|
||||||
socket->close();
|
socket->close();
|
||||||
socket = nullptr;
|
socket = nullptr;
|
||||||
discoveryAgent->start();
|
|
||||||
}
|
}
|
||||||
if (phoneSocket && phoneSocket->isOpen())
|
if (phoneSocket && phoneSocket->isOpen())
|
||||||
{
|
{
|
||||||
phoneSocket->write(AirPodsPackets::Connection::AIRPODS_DISCONNECTED);
|
phoneSocket->write(AirPodsPackets::Connection::AIRPODS_DISCONNECTED);
|
||||||
LOG_DEBUG("AIRPODS_DISCONNECTED packet written: " << AirPodsPackets::Connection::AIRPODS_DISCONNECTED.toHex());
|
LOG_DEBUG("AIRPODS_DISCONNECTED packet written: " << AirPodsPackets::Connection::AIRPODS_DISCONNECTED.toHex());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mediaController->pause(); // Since the device is deconnected, we don't know if it was the active output device. Pause to be safe
|
||||||
|
discoveryAgent->start();
|
||||||
|
|
||||||
|
// Show system notification
|
||||||
|
trayManager->showNotification(
|
||||||
|
tr("AirPods Disconnected"),
|
||||||
|
tr("Your AirPods have been disconnected"));
|
||||||
}
|
}
|
||||||
void bluezDeviceDisconnected(const QString &address)
|
void bluezDeviceDisconnected(const QString &address)
|
||||||
{
|
{
|
||||||
if (address == connectedDeviceMacAddress.replace("_", ":")) {
|
if (address == connectedDeviceMacAddress.replace("_", ":"))
|
||||||
|
{
|
||||||
onDeviceDisconnected(QBluetoothAddress(address));
|
onDeviceDisconnected(QBluetoothAddress(address));
|
||||||
|
|
||||||
|
// Clear the device name and model
|
||||||
|
m_deviceName.clear();
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LOG_WARN("Disconnected device does not match connected device: " << address << " != " << connectedDeviceMacAddress);
|
LOG_WARN("Disconnected device does not match connected device: " << address << " != " << connectedDeviceMacAddress);
|
||||||
|
|||||||
@@ -39,9 +39,14 @@ void MediaController::initializeMprisInterface() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MediaController::handleEarDetection(const QString &status) {
|
void MediaController::handleEarDetection(const QString &status) {
|
||||||
|
bool primaryInEar = false;
|
||||||
|
bool secondaryInEar = false;
|
||||||
|
|
||||||
QStringList parts = status.split(", ");
|
QStringList parts = status.split(", ");
|
||||||
bool primaryInEar = parts[0].contains("In Ear");
|
if (parts.size() == 2) {
|
||||||
bool secondaryInEar = parts[1].contains("In Ear");
|
primaryInEar = parts[0].contains("In Ear");
|
||||||
|
secondaryInEar = parts[1].contains("In Ear");
|
||||||
|
}
|
||||||
|
|
||||||
LOG_DEBUG("Ear detection status: primaryInEar="
|
LOG_DEBUG("Ear detection status: primaryInEar="
|
||||||
<< primaryInEar << ", secondaryInEar=" << secondaryInEar
|
<< primaryInEar << ", secondaryInEar=" << secondaryInEar
|
||||||
@@ -73,14 +78,7 @@ void MediaController::handleEarDetection(const QString &status) {
|
|||||||
QString playbackStatus = process.readAllStandardOutput().trimmed();
|
QString playbackStatus = process.readAllStandardOutput().trimmed();
|
||||||
LOG_DEBUG("Playback status: " << playbackStatus);
|
LOG_DEBUG("Playback status: " << playbackStatus);
|
||||||
if (playbackStatus == "Playing") {
|
if (playbackStatus == "Playing") {
|
||||||
int result = QProcess::execute("playerctl", QStringList() << "pause");
|
pause();
|
||||||
LOG_DEBUG("Executed 'playerctl pause' with result: " << result);
|
|
||||||
if (result == 0) {
|
|
||||||
LOG_INFO("Paused playback via Playerctl");
|
|
||||||
wasPausedByApp = true;
|
|
||||||
} else {
|
|
||||||
LOG_ERROR("Failed to pause playback via Playerctl");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -183,6 +181,20 @@ MediaController::MediaState MediaController::mediaStateFromPlayerctlOutput(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MediaController::pause() {
|
||||||
|
int result = QProcess::execute("playerctl", QStringList() << "pause");
|
||||||
|
LOG_DEBUG("Executed 'playerctl pause' with result: " << result);
|
||||||
|
if (result == 0)
|
||||||
|
{
|
||||||
|
LOG_INFO("Paused playback via Playerctl");
|
||||||
|
wasPausedByApp = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_ERROR("Failed to pause playback via Playerctl");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MediaController::~MediaController() {
|
MediaController::~MediaController() {
|
||||||
if (playerctlProcess) {
|
if (playerctlProcess) {
|
||||||
playerctlProcess->terminate();
|
playerctlProcess->terminate();
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ public:
|
|||||||
void removeAudioOutputDevice();
|
void removeAudioOutputDevice();
|
||||||
void setConnectedDeviceMacAddress(const QString &macAddress);
|
void setConnectedDeviceMacAddress(const QString &macAddress);
|
||||||
|
|
||||||
|
void pause();
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void mediaStateChanged(MediaState state);
|
void mediaStateChanged(MediaState state);
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,11 @@ TrayIconManager::TrayIconManager(QObject *parent) : QObject(parent)
|
|||||||
trayIcon->show();
|
trayIcon->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TrayIconManager::showNotification(const QString &title, const QString &message)
|
||||||
|
{
|
||||||
|
trayIcon->showMessage(title, message, QSystemTrayIcon::Information, 3000);
|
||||||
|
}
|
||||||
|
|
||||||
void TrayIconManager::TrayIconManager::updateBatteryStatus(const QString &status)
|
void TrayIconManager::TrayIconManager::updateBatteryStatus(const QString &status)
|
||||||
{
|
{
|
||||||
trayIcon->setToolTip("Battery Status: " + status);
|
trayIcon->setToolTip("Battery Status: " + status);
|
||||||
@@ -83,9 +88,19 @@ void TrayIconManager::setupMenuActions()
|
|||||||
|
|
||||||
void TrayIconManager::updateIconFromBattery(const QString &status)
|
void TrayIconManager::updateIconFromBattery(const QString &status)
|
||||||
{
|
{
|
||||||
|
int leftLevel = 0;
|
||||||
|
int rightLevel = 0;
|
||||||
|
|
||||||
|
if (!status.isEmpty())
|
||||||
|
{
|
||||||
|
// Parse the battery status string
|
||||||
QStringList parts = status.split(", ");
|
QStringList parts = status.split(", ");
|
||||||
int leftLevel = parts[0].split(": ")[1].replace("%", "").toInt();
|
if (parts.size() >= 2)
|
||||||
int rightLevel = parts[1].split(": ")[1].replace("%", "").toInt();
|
{
|
||||||
|
leftLevel = parts[0].split(": ")[1].replace("%", "").toInt();
|
||||||
|
rightLevel = parts[1].split(": ")[1].replace("%", "").toInt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int minLevel = (leftLevel == 0) ? rightLevel : (rightLevel == 0) ? leftLevel
|
int minLevel = (leftLevel == 0) ? rightLevel : (rightLevel == 0) ? leftLevel
|
||||||
: qMin(leftLevel, rightLevel);
|
: qMin(leftLevel, rightLevel);
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ public:
|
|||||||
|
|
||||||
void updateConversationalAwareness(bool enabled);
|
void updateConversationalAwareness(bool enabled);
|
||||||
|
|
||||||
|
void showNotification(const QString &title, const QString &message);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onTrayIconActivated(QSystemTrayIcon::ActivationReason reason);
|
void onTrayIconActivated(QSystemTrayIcon::ActivationReason reason);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user