mirror of
https://github.com/linuxdeepin/dde-dock.git
synced 2025-06-04 17:33:05 +00:00
631 lines
22 KiB
C++
631 lines
22 KiB
C++
// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd.
|
||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||
//
|
||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||
|
||
#include "soundapplet.h"
|
||
#include "sounddeviceport.h"
|
||
#include "util/horizontalseperator.h"
|
||
#include "../widgets/tipswidget.h"
|
||
#include "../frame/util/imageutil.h"
|
||
#include "util/utils.h"
|
||
|
||
#include <DGuiApplicationHelper>
|
||
#include <DApplication>
|
||
#include <DStandardItem>
|
||
#include <DFontSizeManager>
|
||
#include <DApplicationHelper>
|
||
|
||
#include <QLabel>
|
||
#include <QIcon>
|
||
#include <QScrollBar>
|
||
#include <QPainter>
|
||
#include <QListIterator>
|
||
|
||
#define SEPARATOR_HEIGHT 2
|
||
#define WIDTH 260
|
||
#define MAX_HEIGHT 300
|
||
#define ICON_SIZE 24
|
||
#define ITEM_HEIGHT 24
|
||
#define ITEM_SPACING 5
|
||
#define DEVICE_SPACING 10
|
||
#define SLIDER_HIGHT 70
|
||
#define TITLE_HEIGHT 46
|
||
#define GSETTING_SOUND_OUTPUT_SLIDER "soundOutputSlider"
|
||
|
||
DWIDGET_USE_NAMESPACE
|
||
DGUI_USE_NAMESPACE
|
||
using namespace Dock;
|
||
|
||
SoundApplet::SoundApplet(QWidget *parent)
|
||
: QScrollArea(parent)
|
||
, m_centralWidget(new QWidget(this))
|
||
, m_volumeIconMin(new QLabel(this))
|
||
, m_volumeIconMax(new QLabel(this))
|
||
, m_volumeSlider(new VolumeSlider(this))
|
||
, m_soundShow(new QLabel(this))
|
||
, m_deviceLabel(new QLabel(this))
|
||
, m_seperator(new HorizontalSeperator(this))
|
||
, m_secondSeperator(new HorizontalSeperator(this))
|
||
, m_audioInter(new DBusAudio("org.deepin.dde.Audio1", "/org/deepin/dde/Audio1", QDBusConnection::sessionBus(), this))
|
||
, m_defSinkInter(nullptr)
|
||
, m_listView(new DListView(this))
|
||
, m_model(new QStandardItemModel(m_listView))
|
||
, m_deviceInfo("")
|
||
, m_lastPort(nullptr)
|
||
, m_gsettings(Utils::ModuleSettingsPtr("sound", QByteArray(), this))
|
||
{
|
||
initUi();
|
||
|
||
m_volumeIconMin->installEventFilter(this);
|
||
}
|
||
|
||
void SoundApplet::initUi()
|
||
{
|
||
m_listView->setFrameShape(QFrame::NoFrame);
|
||
m_listView->setEditTriggers(DListView::NoEditTriggers);
|
||
m_listView->setSelectionMode(QAbstractItemView::NoSelection);
|
||
m_listView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||
m_listView->setBackgroundType(DStyledItemDelegate::NoBackground);
|
||
m_listView->setItemRadius(0);
|
||
m_listView->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
|
||
m_listView->setFixedHeight(0);
|
||
m_listView->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||
m_listView->setModel(m_model);
|
||
|
||
m_centralWidget->setAccessibleName("volumn-centralwidget");
|
||
m_volumeIconMin->setAccessibleName("volume-button");
|
||
m_volumeIconMax->setAccessibleName("volume-iconmax");
|
||
m_volumeSlider->setAccessibleName("volume-slider");
|
||
m_soundShow->setAccessibleName("volume-soundtips");
|
||
horizontalScrollBar()->setAccessibleName("volume-horizontalscrollbar");
|
||
verticalScrollBar()->setAccessibleName("volume-verticalscrollbar");
|
||
|
||
m_volumeIconMin->setFixedSize(ICON_SIZE, ICON_SIZE);
|
||
m_volumeIconMax->setFixedSize(ICON_SIZE, ICON_SIZE);
|
||
|
||
m_soundShow->setText(QString("%1%").arg(0));
|
||
m_soundShow->setFixedHeight(TITLE_HEIGHT);
|
||
m_soundShow->setForegroundRole(QPalette::BrightText);
|
||
DFontSizeManager::instance()->bind(m_soundShow, DFontSizeManager::T8, QFont::Medium);
|
||
|
||
m_deviceLabel->setText(tr("Device"));
|
||
m_deviceLabel->setFixedHeight(TITLE_HEIGHT);
|
||
m_deviceLabel->setForegroundRole(QPalette::BrightText);
|
||
DFontSizeManager::instance()->bind(m_deviceLabel, DFontSizeManager::T4, QFont::Medium);
|
||
|
||
m_volumeSlider->setFixedHeight(SLIDER_HIGHT);
|
||
m_volumeSlider->setMinimum(0);
|
||
m_volumeSlider->setMaximum(m_audioInter->maxUIVolume() * 100.0f);
|
||
|
||
// 标题部分
|
||
QHBoxLayout *deviceLayout = new QHBoxLayout;
|
||
deviceLayout->setSpacing(0);
|
||
deviceLayout->setMargin(0);
|
||
deviceLayout->setContentsMargins(20, 0, 10, 0);
|
||
deviceLayout->addWidget(m_deviceLabel, 0, Qt::AlignLeft);
|
||
deviceLayout->addWidget(m_soundShow, 0, Qt::AlignRight);
|
||
|
||
BackgroundWidget *deviceWidget = new BackgroundWidget(this);
|
||
deviceWidget->setLayout(deviceLayout);
|
||
|
||
// 音量滑动条
|
||
QHBoxLayout *volumeCtrlLayout = new QHBoxLayout;
|
||
volumeCtrlLayout->setSpacing(0);
|
||
volumeCtrlLayout->setMargin(0);
|
||
volumeCtrlLayout->setContentsMargins(12, 0, 12, 0);
|
||
volumeCtrlLayout->addWidget(m_volumeIconMin);
|
||
volumeCtrlLayout->addWidget(m_volumeSlider);
|
||
volumeCtrlLayout->addWidget(m_volumeIconMax);
|
||
|
||
BackgroundWidget *volumnWidget = new BackgroundWidget(this);
|
||
volumnWidget->setLayout(volumeCtrlLayout);
|
||
|
||
m_centralLayout = new QVBoxLayout(this);
|
||
m_centralLayout->setContentsMargins(0, 0, 0, 0);
|
||
m_centralLayout->setMargin(0);
|
||
m_centralLayout->setSpacing(0);
|
||
m_centralLayout->addWidget(deviceWidget);
|
||
m_centralLayout->addWidget(m_seperator);
|
||
m_centralLayout->addWidget(volumnWidget);
|
||
// 需要判断是否有声音端口
|
||
m_centralLayout->addWidget(m_secondSeperator);
|
||
|
||
m_centralLayout->addWidget(m_listView);
|
||
m_centralWidget->setLayout(m_centralLayout);
|
||
m_centralWidget->setFixedWidth(WIDTH);
|
||
m_centralWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||
|
||
setFixedWidth(WIDTH);
|
||
setWidget(m_centralWidget);
|
||
setContentsMargins(0, 0, 0, 0);
|
||
setFrameShape(QFrame::NoFrame);
|
||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||
m_centralWidget->setAutoFillBackground(false);
|
||
viewport()->setAutoFillBackground(false);
|
||
m_listView->setItemDelegate(new DStyledItemDelegate(m_listView));
|
||
|
||
m_secondSeperator->setVisible(m_model->rowCount() > 1);
|
||
|
||
updateVolumeSliderStatus(Utils::SettingValue("com.deepin.dde.dock.module.sound", QByteArray(), "Enabled").toString());
|
||
connect(m_gsettings, &QGSettings::changed, [ = ] (const QString &key) {
|
||
if (key == GSETTING_SOUND_OUTPUT_SLIDER) {
|
||
updateVolumeSliderStatus(m_gsettings->get(GSETTING_SOUND_OUTPUT_SLIDER).toString());
|
||
}
|
||
});
|
||
connect(qApp, &QGuiApplication::fontChanged, this, &SoundApplet::updateListHeight);
|
||
connect(m_volumeSlider, &VolumeSlider::valueChanged, this, &SoundApplet::volumeSliderValueChanged);
|
||
connect(m_audioInter, &DBusAudio::DefaultSinkChanged, this, &SoundApplet::onDefaultSinkChanged);
|
||
connect(m_audioInter, &DBusAudio::IncreaseVolumeChanged, this, &SoundApplet::increaseVolumeChanged);
|
||
connect(m_audioInter, &DBusAudio::PortEnabledChanged, [this](uint cardId, QString portId) {
|
||
portEnableChange(cardId, portId);
|
||
});;
|
||
connect(m_listView, &DListView::clicked, this, [this](const QModelIndex & idx) {
|
||
const SoundDevicePort *port = m_listView->model()->data(idx, Qt::WhatsThisPropertyRole).value<const SoundDevicePort *>();
|
||
if (port) {
|
||
m_audioInter->SetPort(port->cardId(), port->id(), int(port->direction()));
|
||
//手动勾选时启用设备
|
||
m_audioInter->SetPortEnabled(port->cardId(), port->id(), true);
|
||
}
|
||
|
||
});
|
||
connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, &SoundApplet::refreshIcon);
|
||
connect(qApp, &DApplication::iconThemeChanged, this, &SoundApplet::refreshIcon);
|
||
QDBusConnection::sessionBus().connect("org.deepin.dde.Audio1", "/org/deepin/dde/Audio1", "org.freedesktop.DBus.Properties"
|
||
,"PropertiesChanged", "sa{sv}as", this, SLOT(haldleDbusSignal(QDBusMessage)));
|
||
|
||
QMetaObject::invokeMethod(this, "onDefaultSinkChanged", Qt::QueuedConnection);
|
||
|
||
refreshIcon();
|
||
|
||
updateCradsInfo();
|
||
}
|
||
|
||
int SoundApplet::volumeValue() const
|
||
{
|
||
return m_volumeSlider->value();
|
||
}
|
||
|
||
int SoundApplet::maxVolumeValue() const
|
||
{
|
||
return m_volumeSlider->maximum();
|
||
}
|
||
|
||
VolumeSlider *SoundApplet::mainSlider()
|
||
{
|
||
return m_volumeSlider;
|
||
}
|
||
|
||
void SoundApplet::onDefaultSinkChanged()
|
||
{
|
||
//防止手动切换设备,与后端交互时,获取到多个信号,设备切换多次,造成混乱
|
||
QThread::msleep(200);
|
||
|
||
if (m_defSinkInter) {
|
||
delete m_defSinkInter;
|
||
m_defSinkInter = nullptr;
|
||
}
|
||
|
||
const QDBusObjectPath defSinkPath = m_audioInter->defaultSink();
|
||
m_defSinkInter = new DBusSink("org.deepin.dde.Audio1", defSinkPath.path(), QDBusConnection::sessionBus(), this);
|
||
|
||
connect(m_defSinkInter, &DBusSink::VolumeChanged, this, &SoundApplet::onVolumeChanged);
|
||
connect(m_defSinkInter, &DBusSink::MuteChanged, this, [ = ] {
|
||
onVolumeChanged(m_defSinkInter->volume() * 100);
|
||
});
|
||
|
||
QString portId = m_defSinkInter->activePort().name;
|
||
uint cardId = m_defSinkInter->card();
|
||
//最后一个设备会被移除,但是当在控制中心选中此设备后需要添加,并勾选
|
||
if (!m_lastPort.isNull() && m_lastPort->cardId() == cardId && m_lastPort->id() == portId) {
|
||
startAddPort(m_lastPort);
|
||
}
|
||
activePort(portId,cardId);
|
||
|
||
//无声卡状态下,会有伪sink设备,显示音量为0
|
||
onVolumeChanged(findPort(portId, cardId) != nullptr ? m_defSinkInter->volume() * 100 : 0);
|
||
emit defaultSinkChanged(m_defSinkInter);
|
||
}
|
||
|
||
void SoundApplet::onVolumeChanged(double volume)
|
||
{
|
||
m_volumeSlider->setValue(std::min(150, qRound(volume * 100.0)));
|
||
m_soundShow->setText(QString::number(volume * 100) + '%');
|
||
emit volumeChanged(m_volumeSlider->value());
|
||
refreshIcon();
|
||
}
|
||
|
||
void SoundApplet::volumeSliderValueChanged()
|
||
{
|
||
m_defSinkInter->SetVolume(m_volumeSlider->value() / 100.0f, true);
|
||
if (m_defSinkInter->mute())
|
||
m_defSinkInter->SetMuteQueued(false);
|
||
}
|
||
|
||
void SoundApplet::cardsChanged(const QString &cards)
|
||
{
|
||
QMap<uint, QStringList> tmpCardIds;
|
||
|
||
QJsonDocument doc = QJsonDocument::fromJson(cards.toUtf8());
|
||
QJsonArray jCards = doc.array();
|
||
for (QJsonValue cV : jCards) {
|
||
QJsonObject jCard = cV.toObject();
|
||
const uint cardId = jCard["Id"].toInt();
|
||
const QString cardName = jCard["Name"].toString();
|
||
QJsonArray jPorts = jCard["Ports"].toArray();
|
||
|
||
QStringList tmpPorts;
|
||
|
||
for (QJsonValue pV : jPorts) {
|
||
QJsonObject jPort = pV.toObject();
|
||
const double portAvai = jPort["Available"].toDouble();
|
||
if (portAvai == 2 || portAvai == 0 ) { // 0 Unknow 1 Not available 2 Available
|
||
const QString portId = jPort["Name"].toString();
|
||
const QString portName = jPort["Description"].toString();
|
||
|
||
SoundDevicePort *port = findPort(portId, cardId);
|
||
const bool include = port != nullptr;
|
||
if (!include) { port = new SoundDevicePort(m_model); }
|
||
|
||
port->setId(portId);
|
||
port->setName(portName);
|
||
port->setDirection(SoundDevicePort::Direction(jPort["Direction"].toDouble()));
|
||
port->setCardId(cardId);
|
||
port->setCardName(cardName);
|
||
|
||
if (!include) {
|
||
startAddPort(port);
|
||
}
|
||
|
||
tmpPorts << portId;
|
||
}
|
||
}
|
||
tmpCardIds.insert(cardId, tmpPorts);
|
||
}
|
||
|
||
onDefaultSinkChanged();//重新获取切换的设备信息
|
||
enableDevice(existActiveOutputDevice());
|
||
|
||
for (SoundDevicePort *port : m_ports) {
|
||
//只要有一个设备在控制中心被禁用后,在任务栏声音设备列表中该设备会被移除,
|
||
if (!m_audioInter->IsPortEnabled(port->cardId(), port->id())) {
|
||
removeDisabledDevice(port->id(), port->cardId());
|
||
}
|
||
//判断端口是否在最新的设备列表中
|
||
if (tmpCardIds.contains(port->cardId())) {
|
||
if (!tmpCardIds[port->cardId()].contains(port->id())) {
|
||
startRemovePort(port->id(), port->cardId());
|
||
}
|
||
}
|
||
else {
|
||
startRemovePort(port->id(), port->cardId());
|
||
}
|
||
}
|
||
//当只有一个设备剩余时,该设备也需要移除
|
||
removeLastDevice();
|
||
updateListHeight();
|
||
}
|
||
|
||
void SoundApplet::increaseVolumeChanged()
|
||
{
|
||
// 触发VolumeSlider::valueChanged
|
||
m_volumeSlider->setMaximum(m_audioInter->maxUIVolume() * 100.0f);
|
||
|
||
// onDefaultSinkChanged()比increaseVolumeChanged()先执行,设置完最大值后需要重新设置当前值
|
||
if (m_defSinkInter) {
|
||
// 规避因开启声音增强,声音值超过100后,关闭声音增强后读取到数据为旧数据的问题
|
||
if (m_audioInter->increaseVolume())
|
||
m_volumeSlider->setValue(std::min(150, qRound(m_defSinkInter->volume() * 100.0)));
|
||
}
|
||
}
|
||
|
||
void SoundApplet::refreshIcon()
|
||
{
|
||
if (!m_defSinkInter)
|
||
return;
|
||
|
||
const bool mute = existActiveOutputDevice() ? m_defSinkInter->mute() : true;
|
||
|
||
QString volumeString;
|
||
|
||
if (mute) {
|
||
volumeString = "muted";
|
||
} else {
|
||
volumeString = "off";
|
||
}
|
||
|
||
QString iconLeft = QString("audio-volume-%1-symbolic").arg(volumeString);
|
||
QString iconRight = QString("audio-volume-high-symbolic");
|
||
|
||
if (DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::LightType) {
|
||
iconLeft.append("-dark");
|
||
iconRight.append("-dark");
|
||
}
|
||
|
||
const auto ratio = devicePixelRatioF();
|
||
QPixmap ret = ImageUtil::loadSvg(iconRight, ":/", ICON_SIZE, ratio);
|
||
m_volumeIconMax->setPixmap(ret);
|
||
|
||
ret = ImageUtil::loadSvg(iconLeft, ":/", ICON_SIZE, ratio);
|
||
m_volumeIconMin->setPixmap(ret);
|
||
}
|
||
|
||
/**
|
||
* @brief SoundApplet::startAddPort 添加端口前判断
|
||
* @param port 端口
|
||
*/
|
||
void SoundApplet::startAddPort(SoundDevicePort *port)
|
||
{
|
||
if (!containsPort(port) && port->direction() == SoundDevicePort::Out) {
|
||
m_ports.append(port);
|
||
addPort(port);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief SoundApplet::startRemovePort 移除端口前判断
|
||
* @param portId 端口
|
||
* @param cardId 声卡
|
||
*/
|
||
void SoundApplet::startRemovePort(const QString &portId, const uint &cardId)
|
||
{
|
||
SoundDevicePort *port = findPort(portId, cardId);
|
||
if (port) {
|
||
m_ports.removeOne(port);
|
||
port->deleteLater();
|
||
removePort(portId, cardId);
|
||
}
|
||
}
|
||
|
||
bool SoundApplet::containsPort(const SoundDevicePort *port)
|
||
{
|
||
return findPort(port->id(), port->cardId()) != nullptr;
|
||
}
|
||
|
||
SoundDevicePort *SoundApplet::findPort(const QString &portId, const uint &cardId) const
|
||
{
|
||
auto it = std::find_if(m_ports.begin(), m_ports.end(), [ = ] (SoundDevicePort *p) {
|
||
return (p->id() == portId && p->cardId() == cardId);
|
||
});
|
||
|
||
if (it != m_ports.end()) {
|
||
return *it;
|
||
}
|
||
|
||
return nullptr;
|
||
}
|
||
|
||
void SoundApplet::addPort(const SoundDevicePort *port)
|
||
{
|
||
DStandardItem *pi = new DStandardItem;
|
||
QString deviceName = port->name() + "(" + port->cardName() + ")";
|
||
pi->setText(deviceName);
|
||
pi->setTextColorRole(QPalette::BrightText);
|
||
pi->setData(QVariant::fromValue<const SoundDevicePort *>(port), Qt::WhatsThisPropertyRole);
|
||
|
||
connect(port, &SoundDevicePort::nameChanged, this, [ = ](const QString &str) {
|
||
QString devName = str + "(" + port->cardName() + ")";
|
||
pi->setText(devName);
|
||
});
|
||
connect(port, &SoundDevicePort::cardNameChanged, this, [ = ](const QString &str) {
|
||
QString devName = port->name() + "(" + str + ")";
|
||
pi->setText(devName);
|
||
});
|
||
connect(port, &SoundDevicePort::isActiveChanged, this, [ = ](bool isActive) {
|
||
pi->setCheckState(isActive ? Qt::CheckState::Checked : Qt::CheckState::Unchecked);
|
||
});
|
||
|
||
if (port->isActive()) {
|
||
pi->setCheckState(Qt::CheckState::Checked);
|
||
}
|
||
|
||
m_model->appendRow(pi);
|
||
m_model->sort(0);
|
||
m_secondSeperator->setVisible(m_model->rowCount() > 1);
|
||
updateListHeight();
|
||
}
|
||
|
||
void SoundApplet::removePort(const QString &portId, const uint &cardId)
|
||
{
|
||
auto rmFunc = [ = ](QStandardItemModel * model) {
|
||
for (int i = 0; i < model->rowCount();) {
|
||
auto item = model->item(i);
|
||
auto port = item->data(Qt::WhatsThisPropertyRole).value<const SoundDevicePort *>();
|
||
if (port->id() == portId && cardId == port->cardId()) {
|
||
model->removeRow(i);
|
||
break;
|
||
} else {
|
||
++i;
|
||
}
|
||
}
|
||
};
|
||
|
||
rmFunc(m_model);
|
||
m_secondSeperator->setVisible(m_model->rowCount() > 1);
|
||
updateListHeight();
|
||
}
|
||
|
||
/**
|
||
* @brief SoundApplet::activePort 激活某一指定端口
|
||
* @param portId 端口
|
||
* @param cardId 声卡
|
||
*/
|
||
void SoundApplet::activePort(const QString &portId, const uint &cardId)
|
||
{
|
||
for (SoundDevicePort *it : m_ports) {
|
||
if (it->id() == portId && it->cardId() == cardId) {
|
||
it->setIsActive(true);
|
||
enableDevice(true);
|
||
}
|
||
else {
|
||
it->setIsActive(false);
|
||
}
|
||
}
|
||
}
|
||
|
||
void SoundApplet::updateCradsInfo()
|
||
{
|
||
QString info = m_audioInter->property("CardsWithoutUnavailable").toString();
|
||
if(m_deviceInfo != info){
|
||
cardsChanged(info);
|
||
m_deviceInfo = info;
|
||
}
|
||
}
|
||
|
||
void SoundApplet::enableDevice(bool flag)
|
||
{
|
||
QString status = m_gsettings ? m_gsettings->get(GSETTING_SOUND_OUTPUT_SLIDER).toString() : "Enabled";
|
||
if ("Disabled" == status ) {
|
||
m_volumeSlider->setEnabled(false);
|
||
} else if ("Enabled" == status) {
|
||
m_volumeSlider->setEnabled(flag);
|
||
}
|
||
m_volumeIconMin->setEnabled(flag);
|
||
m_soundShow->setEnabled(flag);
|
||
m_volumeIconMax->setEnabled(flag);
|
||
m_deviceLabel->setEnabled(flag);
|
||
}
|
||
|
||
void SoundApplet::disableAllDevice()
|
||
{
|
||
for (SoundDevicePort *port : m_ports) {
|
||
port->setIsActive(false);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief SoundApplet::removeLastDevice
|
||
* 移除最后一个设备
|
||
*/
|
||
void SoundApplet::removeLastDevice()
|
||
{
|
||
if (m_ports.count() == 1 && m_ports.at(0)) {
|
||
m_lastPort = new SoundDevicePort(m_model);
|
||
m_lastPort->setId(m_ports.at(0)->id());
|
||
m_lastPort->setName(m_ports.at(0)->name());
|
||
m_lastPort->setDirection(m_ports.at(0)->direction());
|
||
m_lastPort->setCardId(m_ports.at(0)->cardId());
|
||
m_lastPort->setCardName(m_ports.at(0)->cardName());
|
||
startRemovePort(m_ports.at(0)->id(), m_ports.at(0)->cardId());
|
||
qDebug() << "remove last output device";
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief SoundApplet::removeDisabledDevice 移除禁用设备
|
||
* @param portId
|
||
* @param cardId
|
||
*/
|
||
void SoundApplet::removeDisabledDevice(QString portId, unsigned int cardId)
|
||
{
|
||
startRemovePort(portId, cardId);
|
||
if (m_defSinkInter->activePort().name == portId && m_defSinkInter->card() == cardId) {
|
||
enableDevice(false);
|
||
disableAllDevice();
|
||
}
|
||
qDebug() << "remove disabled output device";
|
||
}
|
||
|
||
void SoundApplet::updateVolumeSliderStatus(const QString &status)
|
||
{
|
||
bool flag = true;
|
||
if ("Enabled" == status) {
|
||
flag = true;
|
||
} else if ("Disabled" == status) {
|
||
flag = false;
|
||
}
|
||
m_volumeSlider->setEnabled(flag);
|
||
m_volumeIconMin->setEnabled(flag);
|
||
m_volumeIconMax->setEnabled(flag);
|
||
|
||
flag = "Hiden" != status;
|
||
m_volumeSlider->setVisible(flag);
|
||
m_volumeIconMin->setVisible(flag);
|
||
m_volumeIconMax->setVisible(flag);
|
||
}
|
||
|
||
/** 判断是否存在未禁用的声音输出设备
|
||
* @brief SoundApplet::existActiveOutputDevice
|
||
* @return 存在返回true,否则返回false
|
||
*/
|
||
bool SoundApplet::existActiveOutputDevice()
|
||
{
|
||
QString info = m_audioInter->property("CardsWithoutUnavailable").toString();
|
||
|
||
QJsonDocument doc = QJsonDocument::fromJson(info.toUtf8());
|
||
QJsonArray jCards = doc.array();
|
||
for (QJsonValue cV : jCards) {
|
||
QJsonObject jCard = cV.toObject();
|
||
QJsonArray jPorts = jCard["Ports"].toArray();
|
||
|
||
for (QJsonValue pV : jPorts) {
|
||
QJsonObject jPort = pV.toObject();
|
||
if (jPort["Direction"].toInt() == 1 && jPort["Enabled"].toBool())
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
bool SoundApplet::eventFilter(QObject *watcher, QEvent *event)
|
||
{
|
||
// 当控制中心禁用所有输出设备时,静音按钮置灰,其他情况正常.
|
||
if (watcher == m_volumeIconMin && event->type() == QEvent::MouseButtonRelease) {
|
||
if (!existActiveOutputDevice()) {
|
||
m_volumeIconMin->setEnabled(false);
|
||
} else {
|
||
m_volumeIconMin->setEnabled(true);
|
||
m_defSinkInter->SetMuteQueued(!m_defSinkInter->mute());
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
void SoundApplet::haldleDbusSignal(const QDBusMessage &msg)
|
||
{
|
||
Q_UNUSED(msg)
|
||
|
||
updateCradsInfo();
|
||
}
|
||
|
||
void SoundApplet::updateListHeight()
|
||
{
|
||
//设备数多于10个时显示滚动条,固定高度
|
||
int count = m_model->rowCount() == 1 ? 0 : m_model->rowCount();
|
||
|
||
if (m_model->rowCount() > 10) {
|
||
count = 10;
|
||
m_listView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||
} else {
|
||
m_listView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||
}
|
||
|
||
int visualHeight = 0;
|
||
for (int i = 0; i < count; i++)
|
||
visualHeight += m_listView->visualRect(m_model->index(i, 0)).height();
|
||
|
||
int listMargin = m_listView->contentsMargins().top() + m_listView->contentsMargins().bottom();
|
||
//显示声音设备列表高度 = 设备的高度 + 间隔 + 边距
|
||
int viewHeight = visualHeight + m_listView->spacing() * (count - 1) + listMargin;
|
||
// 设备信息高度 = 设备标签 + 分隔线 + 滚动条 + 间隔
|
||
int labelHeight = m_deviceLabel->height() > m_soundShow->height() ? m_deviceLabel->height() : m_soundShow->height();
|
||
int infoHeight = labelHeight + m_seperator->height() * 2 + m_volumeSlider->height();
|
||
int margain = m_centralLayout->contentsMargins().top() + m_centralLayout->contentsMargins().bottom();
|
||
//整个界面高度 = 显示声音设备列表高度 + 设备信息高度 + 边距
|
||
int totalHeight = viewHeight + infoHeight + margain;
|
||
//加上分割线占用的高度,否则显示界面高度不够显示,会造成音频列表item最后一项比其它项的高度小
|
||
m_listView->setFixedHeight(viewHeight);
|
||
setFixedHeight(totalHeight);
|
||
m_centralWidget->setFixedHeight(totalHeight);
|
||
}
|
||
|
||
void SoundApplet::portEnableChange(unsigned int cardId, QString portId)
|
||
{
|
||
Q_UNUSED(cardId)
|
||
Q_UNUSED(portId)
|
||
m_deviceInfo = "";
|
||
updateCradsInfo();
|
||
}
|