4 Commits

Author SHA1 Message Date
Mathias S.
d7a96c9fc5 Fix: Activate A2DP audio profile for AirPods after system reboot on Linx (#212)
Fix: Activate A2DP audio profile for AirPods after system reboot

- Add A2DP profile activation on system wake-up
- Add A2DP profile activation when BlueZ detects connection
- Add A2DP profile activation for already connected devices on startup

Fixes issue where AirPods microphone works but audio output is unavailable after reboot
2025-09-30 14:17:16 +05:30
Kavish Devar
b732c66962 linux: add desktop entry file (#204) 2025-09-23 10:12:37 +05:30
Integral
f5742618c7 linux: add desktop entry file 2025-09-17 10:19:52 +08:00
Kavish Devar
802c2e0220 linux: fix app name 2025-09-03 13:48:57 +05:30
5 changed files with 61 additions and 9 deletions

View File

@@ -75,3 +75,5 @@ install(TARGETS librepods
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
install(FILES assets/me.kavishdevar.librepods.desktop
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications")

View File

@@ -8,7 +8,7 @@ ApplicationWindow {
visible: !airPodsTrayApp.hideOnStart
width: 400
height: 300
title: "Librepods"
title: "LibrePods"
objectName: "mainWindowObject"
onClosing: mainWindow.visible = false

View File

@@ -0,0 +1,9 @@
[Desktop Entry]
Version=1.0
Type=Application
Name=LibrePods
Comment=AirPods libreated from Apple's ecosystem
Exec=librepods
Icon=librepods
Terminal=false
Categories=Audio;AudioVideo;Utility;Qt;

View File

@@ -3,9 +3,9 @@
#include <QDebug>
#include <QLoggingCategory>
Q_DECLARE_LOGGING_CATEGORY(Librepods)
Q_DECLARE_LOGGING_CATEGORY(librepods)
#define LOG_INFO(msg) qCInfo(Librepods) << "\033[32m" << msg << "\033[0m"
#define LOG_WARN(msg) qCWarning(Librepods) << "\033[33m" << msg << "\033[0m"
#define LOG_ERROR(msg) qCCritical(Librepods) << "\033[31m" << msg << "\033[0m"
#define LOG_DEBUG(msg) qCDebug(Librepods) << "\033[34m" << msg << "\033[0m"
#define LOG_INFO(msg) qCInfo(librepods) << "\033[32m" << msg << "\033[0m"
#define LOG_WARN(msg) qCWarning(librepods) << "\033[33m" << msg << "\033[0m"
#define LOG_ERROR(msg) qCCritical(librepods) << "\033[31m" << msg << "\033[0m"
#define LOG_DEBUG(msg) qCDebug(librepods) << "\033[34m" << msg << "\033[0m"

View File

@@ -29,7 +29,7 @@
using namespace AirpodsTrayApp::Enums;
Q_LOGGING_CATEGORY(Librepods, "Librepods")
Q_LOGGING_CATEGORY(librepods, "librepods")
class AirPodsTrayApp : public QObject {
Q_OBJECT
@@ -50,8 +50,8 @@ public:
, m_deviceInfo(new DeviceInfo(this)), m_bleManager(new BleManager(this))
, m_systemSleepMonitor(new SystemSleepMonitor(this))
{
QLoggingCategory::setFilterRules(QString("Librepods.debug=%1").arg(debugMode ? "true" : "false"));
LOG_INFO("Initializing AirPodsTrayApp");
QLoggingCategory::setFilterRules(QString("librepods.debug=%1").arg(debugMode ? "true" : "false"));
LOG_INFO("Initializing LibrePods");
// Initialize tray icon and connect signals
trayManager = new TrayIconManager(this);
@@ -96,6 +96,15 @@ public:
QBluetoothDeviceInfo device(address, "", 0);
if (isAirPodsDevice(device)) {
connectToDevice(device);
// On startup after reboot, activate A2DP profile for already connected AirPods
QTimer::singleShot(2000, this, [this, address]()
{
QString formattedAddress = address.toString().replace(":", "_");
mediaController->setConnectedDeviceMacAddress(formattedAddress);
mediaController->activateA2dpProfile();
LOG_INFO("A2DP profile activation attempted for AirPods found on startup");
});
return;
}
}
@@ -397,6 +406,23 @@ public slots:
{
LOG_INFO("System is waking up, starting ble scan");
m_bleManager->startScan();
// Check if AirPods are already connected and activate A2DP profile
if (areAirpodsConnected() && m_deviceInfo && !m_deviceInfo->bluetoothAddress().isEmpty())
{
LOG_INFO("AirPods already connected after wake-up, re-activating A2DP profile");
mediaController->setConnectedDeviceMacAddress(m_deviceInfo->bluetoothAddress().replace(":", "_"));
// Always activate A2DP profile after system wake since the profile might have been lost
QTimer::singleShot(1000, this, [this]()
{
mediaController->activateA2dpProfile();
LOG_INFO("A2DP profile activation attempted after system wake-up");
});
}
// Also check for already connected devices via BlueZ
monitor->checkAlreadyConnectedDevices();
}
private slots:
@@ -445,6 +471,20 @@ private slots:
{
QBluetoothDeviceInfo device(QBluetoothAddress(address), name, 0);
connectToDevice(device);
// After system reboot, AirPods might be connected but A2DP profile not active
// Attempt to activate A2DP profile after a delay to ensure connection is established
QTimer::singleShot(2000, this, [this, address]()
{
if (!address.isEmpty())
{
QString formattedAddress = address;
formattedAddress = formattedAddress.replace(":", "_");
mediaController->setConnectedDeviceMacAddress(formattedAddress);
mediaController->activateA2dpProfile();
LOG_INFO("A2DP profile activation attempted for newly connected device");
}
});
}
void onDeviceDisconnected(const QBluetoothAddress &address)
@@ -951,6 +991,7 @@ int main(int argc, char *argv[]) {
LOG_DEBUG("Socket error: " << socket.errorString());
}
}
app.setDesktopFileName("me.kavishdevar.librepods");
app.setQuitOnLastWindowClosed(false);
bool debugMode = false;