111 lines
3.1 KiB
C++
111 lines
3.1 KiB
C++
#include "trayicon.h"
|
|
|
|
#include <QMenu>
|
|
#include <QApplication>
|
|
#include <QAction>
|
|
#include <QDebug>
|
|
|
|
#include <pulse/pulseaudio.h>
|
|
|
|
TrayIcon::TrayIcon(QObject *parent) :
|
|
QSystemTrayIcon(QIcon::fromTheme("preferences-desktop-sound"), parent),
|
|
pulse(this)
|
|
{
|
|
this->menu = new QMenu(); // can only be explicitly owned by a QWidget, not any QObject, so we need to
|
|
// manually manage its lifecycle in the d'tor
|
|
|
|
this->quitAction = new QAction("Quit");
|
|
connect(this->quitAction, &QAction::triggered, this, &TrayIcon::on_quitAction_triggered);
|
|
|
|
this->refreshAction = new QAction("Refresh");
|
|
connect(this->refreshAction, &QAction::triggered, this, &TrayIcon::onRefreshAction_triggered);
|
|
|
|
// Set up basic menu only, will be wiped during refresh
|
|
this->menu->addAction(refreshAction);
|
|
this->menu->addAction(quitAction);
|
|
|
|
this->setContextMenu(this->menu); // n.b. does not take ownership
|
|
|
|
connect(&this->pulse, &QPulse::ConnectionStateChanged, [=]() {
|
|
if (pulse.ConnectionState() == PA_CONTEXT_READY) {
|
|
refreshData();
|
|
}
|
|
});
|
|
connect(&this->pulse, &QPulse::GotCardInfoList, this, &TrayIcon::onGotPulseCardInfo);
|
|
|
|
refreshData();
|
|
}
|
|
|
|
TrayIcon::~TrayIcon()
|
|
{
|
|
for (int i = 0; i < cardMenus.length(); ++i) {
|
|
delete cardMenus[i];
|
|
}
|
|
cardMenus.clear();
|
|
delete this->quitAction;
|
|
delete this->menu;
|
|
}
|
|
|
|
void TrayIcon::refreshData()
|
|
{
|
|
// Delete existing card menus, but leave the final clearing for later
|
|
for (int i = 0; i < cardMenus.length(); ++i) {
|
|
delete cardMenus[i];
|
|
}
|
|
cardMenus.clear();
|
|
|
|
// Calling delete() should have removed them from the menu, leaving only the separator / refresh / quit options
|
|
|
|
pulse.RequestCardInfo();
|
|
}
|
|
|
|
void TrayIcon::on_quitAction_triggered()
|
|
{
|
|
QApplication::exit(0);
|
|
}
|
|
|
|
void TrayIcon::onRefreshAction_triggered()
|
|
{
|
|
refreshData();
|
|
}
|
|
|
|
void TrayIcon::onGotPulseCardInfo(const pa_card_info *cardInfo, int eol)
|
|
{
|
|
if (eol) {
|
|
// OK - rebuild the menu
|
|
this->menu->clear();
|
|
|
|
for (int i = 0; i < this->cardMenus.length(); ++i) {
|
|
this->menu->addMenu(this->cardMenus[i]);
|
|
}
|
|
this->menu->addSeparator();
|
|
this->menu->addAction(refreshAction);
|
|
this->menu->addAction(quitAction);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
QString name; // = pa_proplist_to_string(cardInfo->proplist);; // copy to QString from internally-managed buffers
|
|
if (true) { // 0 != pa_proplist_isempty(cardInfo->proplist) && 1 == pa_proplist_contains(cardInfo->proplist, PA_PROP_DEVICE_DESCRIPTION)) {
|
|
name = pa_proplist_gets(cardInfo->proplist, PA_PROP_DEVICE_DESCRIPTION);;
|
|
} else {
|
|
name = cardInfo->name;
|
|
}
|
|
*/
|
|
|
|
/*
|
|
QString name(cardInfo->name);
|
|
if (name.length() == 0) {
|
|
name = tr("Default card");
|
|
}
|
|
*/
|
|
|
|
QMenu* cardMenu = new QMenu(name);
|
|
for (size_t i = 0; i < cardInfo->n_profiles; ++i) {
|
|
auto profileAction = new QAction(cardInfo->profiles[i].description, cardMenu);
|
|
cardMenu->addAction(profileAction);
|
|
}
|
|
|
|
this->cardMenus.push_back(cardMenu);
|
|
}
|