#include #include #include #include #include #include #include #include #include #include #include "netlinkmonitor.h" // KStatusNotifierItem from KF6::Notifications #include #include // if you want i18n (need KF6I18n) #define BUF_LEN (10 * (sizeof(struct inotify_event) + NAME_MAX + 1)) static QString readSysfsFile(const QString &path) { QFile file(path); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { qWarning() << "Cannot open sysfs:" << path; return QString(); } QTextStream in(&file); return in.readLine().trimmed(); } int main(int argc, char *argv[]) { // Use QApplication because we need a GUI event loop for system tray icons QApplication app(argc, argv); // 1) Create our tray icon via KStatusNotifierItem KStatusNotifierItem *trayIcon = new KStatusNotifierItem; trayIcon->setTitle(QStringLiteral("JBL Quantum 610")); trayIcon->setIconByName(QStringLiteral("audio-headset")); // (You can also set a custom icon path with setIconByPixmap) // 2) Set category & status trayIcon->setCategory(KStatusNotifierItem::Hardware); trayIcon->setStatus(KStatusNotifierItem::Active); // 3) Function to update the tray tooltip with sysfs data auto updateTray = [trayIcon]() { // Example sysfs paths: adjust to your kernel module's actual files QString batteryStr = readSysfsFile(QStringLiteral("/sys/class/power_supply/JBL_Quantum_610/capacity")); QString micMuteStr = readSysfsFile(QStringLiteral("/sys/bus/hid/devices/0003:0ECB:205C.0007/mic_mute")); if (batteryStr.isEmpty()) { batteryStr = QStringLiteral("?"); } bool isMuted = (micMuteStr.trimmed() == QLatin1String("1")); // Compose tooltip title and subtitle QString tooltipTitle = QStringLiteral("JBL Quantum 610"); QString tooltipSubTitle = QStringLiteral("Battery: %1%\nMic: %2") .arg(batteryStr) .arg(isMuted ? QStringLiteral("Muted") : QStringLiteral("Unmuted")); trayIcon->setToolTipTitle(tooltipTitle); trayIcon->setToolTipSubTitle(tooltipSubTitle); // Optionally change the icon depending on battery level / mute // For example: int batteryVal = batteryStr.toInt(); if (batteryVal < 20) { trayIcon->setIconByName(QStringLiteral("battery-caution")); } else { trayIcon->setIconByName(QStringLiteral("audio-headset")); } }; // 4) QTimer to update every 10 seconds (example) QTimer timer; //QObject::connect(&timer, &QTimer::timeout, updateTray); //timer.start(10000); NetlinkMonitor netlinkMonitor; if (!netlinkMonitor.setupNetlink()) { qWarning("Failed to setup netlink socket. Exiting..."); return -1; } updateTray(); QObject::connect(&netlinkMonitor, &NetlinkMonitor::messageReceived, [trayIcon](const QString &msg) { printf("%s\n", msg.toStdString().c_str()); if (msg == QStringLiteral("JBL610_DEVICE_MUTED")) { printf("MUTED"); trayIcon->setIconByName(QStringLiteral("audio-headphones")); } else { trayIcon->setIconByName(QStringLiteral("audio-headset")); printf("UNMUTED"); } }); // Call once at startup // 5) Show the tray icon (KStatusNotifierItem auto-shows if the desktop supports it) return app.exec(); }