fix: 修复任务栏插件音量设备显示错误的问题

音量设备解析错误,没有和控制中心保持一致,参照之前的音量的解析逻辑重新来显示音量的功能即可

Log:
Influence: 从任务栏打开音量,进入音量的详情页面,观察是否和控制中心一致
Bug: https://pms.uniontech.com/bug-view-165853.html
Change-Id: I39a6b0664ac2adc40f2ea523d8e0693426640ae5
This commit is contained in:
donghualin 2022-11-24 08:14:19 +00:00
parent 5f4c199ccc
commit ec092bb980
8 changed files with 446 additions and 184 deletions

View File

@ -20,6 +20,7 @@
*/
#include "soundapplet.h"
#include "sounddeviceport.h"
#include "util/horizontalseperator.h"
#include "../widgets/tipswidget.h"
#include "../frame/util/imageutil.h"
@ -52,64 +53,6 @@ DWIDGET_USE_NAMESPACE
DGUI_USE_NAMESPACE
using namespace Dock;
Q_DECLARE_METATYPE(const Port *)
Port::Port(QObject *parent)
: QObject(parent)
, m_isActive(false)
, m_direction(Out)
{
}
void Port::setId(const QString &id)
{
if (id != m_id) {
m_id = id;
Q_EMIT idChanged(id);
}
}
void Port::setName(const QString &name)
{
if (name != m_name) {
m_name = name;
Q_EMIT nameChanged(name);
}
}
void Port::setCardName(const QString &cardName)
{
if (cardName != m_cardName) {
m_cardName = cardName;
Q_EMIT cardNameChanged(cardName);
}
}
void Port::setIsActive(bool isActive)
{
if (isActive != m_isActive) {
m_isActive = isActive;
Q_EMIT isActiveChanged(isActive);
}
}
void Port::setDirection(const Direction &direction)
{
if (direction != m_direction) {
m_direction = direction;
Q_EMIT directionChanged(direction);
}
}
void Port::setCardId(const uint &cardId)
{
if (cardId != m_cardId) {
m_cardId = cardId;
Q_EMIT cardIdChanged(cardId);
}
}
SoundApplet::SoundApplet(QWidget *parent)
: QScrollArea(parent)
, m_centralWidget(new QWidget(this))
@ -235,7 +178,7 @@ void SoundApplet::initUi()
portEnableChange(cardId, portId);
});;
connect(m_listView, &DListView::clicked, this, [this](const QModelIndex & idx) {
const Port * port = m_listView->model()->data(idx, Qt::WhatsThisPropertyRole).value<const Port *>();
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()));
//手动勾选时启用设备
@ -337,13 +280,13 @@ void SoundApplet::cardsChanged(const QString &cards)
const QString portId = jPort["Name"].toString();
const QString portName = jPort["Description"].toString();
Port *port = findPort(portId, cardId);
SoundDevicePort *port = findPort(portId, cardId);
const bool include = port != nullptr;
if (!include) { port = new Port(m_model); }
if (!include) { port = new SoundDevicePort(m_model); }
port->setId(portId);
port->setName(portName);
port->setDirection(Port::Direction(jPort["Direction"].toDouble()));
port->setDirection(SoundDevicePort::Direction(jPort["Direction"].toDouble()));
port->setCardId(cardId);
port->setCardName(cardName);
@ -360,7 +303,7 @@ void SoundApplet::cardsChanged(const QString &cards)
onDefaultSinkChanged();//重新获取切换的设备信息
enableDevice(existActiveOutputDevice());
for (Port *port : m_ports) {
for (SoundDevicePort *port : m_ports) {
//只要有一个设备在控制中心被禁用后,在任务栏声音设备列表中该设备会被移除,
if (!m_audioInter->IsPortEnabled(port->cardId(), port->id())) {
removeDisabledDevice(port->id(), port->cardId());
@ -428,9 +371,9 @@ void SoundApplet::refreshIcon()
* @brief SoundApplet::startAddPort
* @param port
*/
void SoundApplet::startAddPort(Port *port)
void SoundApplet::startAddPort(SoundDevicePort *port)
{
if (!containsPort(port) && port->direction() == Port::Out) {
if (!containsPort(port) && port->direction() == SoundDevicePort::Out) {
m_ports.append(port);
addPort(port);
}
@ -443,7 +386,7 @@ void SoundApplet::startAddPort(Port *port)
*/
void SoundApplet::startRemovePort(const QString &portId, const uint &cardId)
{
Port *port = findPort(portId, cardId);
SoundDevicePort *port = findPort(portId, cardId);
if (port) {
m_ports.removeOne(port);
port->deleteLater();
@ -451,14 +394,14 @@ void SoundApplet::startRemovePort(const QString &portId, const uint &cardId)
}
}
bool SoundApplet::containsPort(const Port *port)
bool SoundApplet::containsPort(const SoundDevicePort *port)
{
return findPort(port->id(), port->cardId()) != nullptr;
}
Port *SoundApplet::findPort(const QString &portId, const uint &cardId) const
SoundDevicePort *SoundApplet::findPort(const QString &portId, const uint &cardId) const
{
auto it = std::find_if(m_ports.begin(), m_ports.end(), [ = ] (Port *p) {
auto it = std::find_if(m_ports.begin(), m_ports.end(), [ = ] (SoundDevicePort *p) {
return (p->id() == portId && p->cardId() == cardId);
});
@ -469,23 +412,23 @@ Port *SoundApplet::findPort(const QString &portId, const uint &cardId) const
return nullptr;
}
void SoundApplet::addPort(const Port *port)
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 Port *>(port), Qt::WhatsThisPropertyRole);
pi->setData(QVariant::fromValue<const SoundDevicePort *>(port), Qt::WhatsThisPropertyRole);
connect(port, &Port::nameChanged, this, [ = ](const QString &str) {
connect(port, &SoundDevicePort::nameChanged, this, [ = ](const QString &str) {
QString devName = str + "(" + port->cardName() + ")";
pi->setText(devName);
});
connect(port, &Port::cardNameChanged, this, [ = ](const QString &str) {
connect(port, &SoundDevicePort::cardNameChanged, this, [ = ](const QString &str) {
QString devName = port->name() + "(" + str + ")";
pi->setText(devName);
});
connect(port, &Port::isActiveChanged, this, [ = ](bool isActive) {
connect(port, &SoundDevicePort::isActiveChanged, this, [ = ](bool isActive) {
pi->setCheckState(isActive ? Qt::CheckState::Checked : Qt::CheckState::Unchecked);
});
@ -504,7 +447,7 @@ 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 Port *>();
auto port = item->data(Qt::WhatsThisPropertyRole).value<const SoundDevicePort *>();
if (port->id() == portId && cardId == port->cardId()) {
model->removeRow(i);
break;
@ -526,7 +469,7 @@ void SoundApplet::removePort(const QString &portId, const uint &cardId)
*/
void SoundApplet::activePort(const QString &portId, const uint &cardId)
{
for (Port *it : m_ports) {
for (SoundDevicePort *it : m_ports) {
if (it->id() == portId && it->cardId() == cardId) {
it->setIsActive(true);
enableDevice(true);
@ -562,7 +505,7 @@ void SoundApplet::enableDevice(bool flag)
void SoundApplet::disableAllDevice()
{
for (Port *port : m_ports) {
for (SoundDevicePort *port : m_ports) {
port->setIsActive(false);
}
}
@ -574,7 +517,7 @@ void SoundApplet::disableAllDevice()
void SoundApplet::removeLastDevice()
{
if (m_ports.count() == 1 && m_ports.at(0)) {
m_lastPort = new Port(m_model);
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());

View File

@ -43,58 +43,12 @@ using DBusSink = org::deepin::daemon::audio1::Sink;
class HorizontalSeperator;
class QGSettings;
class SoundDevicePort;
namespace Dock {
class TipsWidget;
}
class Port : public QObject
{
Q_OBJECT
public:
enum Direction {
Out = 1,
In = 2
};
explicit Port(QObject *parent = nullptr);
virtual ~Port() {}
inline QString id() const { return m_id; }
void setId(const QString &id);
inline QString name() const { return m_name; }
void setName(const QString &name);
inline QString cardName() const { return m_cardName; }
void setCardName(const QString &cardName);
inline bool isActive() const { return m_isActive; }
void setIsActive(bool isActive);
inline Direction direction() const { return m_direction; }
void setDirection(const Direction &direction);
inline uint cardId() const { return m_cardId; }
void setCardId(const uint &cardId);
Q_SIGNALS:
void idChanged(QString id) const;
void nameChanged(QString name) const;
void cardNameChanged(QString name) const;
void isActiveChanged(bool ative) const;
void directionChanged(Direction direction) const;
void cardIdChanged(uint cardId) const;
private:
QString m_id;
QString m_name;
uint m_cardId;
QString m_cardName;
bool m_isActive;
Direction m_direction;
};
class BackgroundWidget : public QWidget
{
public:
@ -128,10 +82,10 @@ public:
int volumeValue() const;
int maxVolumeValue() const;
VolumeSlider *mainSlider();
void startAddPort(Port *port);
void startAddPort(SoundDevicePort *port);
void startRemovePort(const QString &portId, const uint &cardId);
bool containsPort(const Port *port);
Port *findPort(const QString &portId, const uint &cardId) const;
bool containsPort(const SoundDevicePort *port);
SoundDevicePort *findPort(const QString &portId, const uint &cardId) const;
void setUnchecked(DStandardItem *pi);
void initUi();
@ -148,7 +102,7 @@ private slots:
void increaseVolumeChanged();
void cardsChanged(const QString &cards);
void removePort(const QString &portId, const uint &cardId);
void addPort(const Port *port);
void addPort(const SoundDevicePort *port);
void activePort(const QString &portId,const uint &cardId);
void haldleDbusSignal(const QDBusMessage &msg);
void updateListHeight();
@ -181,9 +135,9 @@ private:
DBusSink *m_defSinkInter;
DTK_WIDGET_NAMESPACE::DListView *m_listView;
QStandardItemModel *m_model;
QList<Port *> m_ports;
QList<SoundDevicePort *> m_ports;
QString m_deviceInfo;
QPointer<Port> m_lastPort;//最后一个因为只有一个设备而被直接移除的设备
QPointer<SoundDevicePort> m_lastPort;//最后一个因为只有一个设备而被直接移除的设备
const QGSettings *m_gsettings;
};

View File

@ -0,0 +1,80 @@
/*
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
*
* Author: donghualin <donghualin@uniontech.com>
*
* Maintainer: donghualin <donghualin@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "sounddeviceport.h"
SoundDevicePort::SoundDevicePort(QObject *parent)
: QObject(parent)
, m_isActive(false)
, m_direction(Out)
{
}
SoundDevicePort::~SoundDevicePort()
{
}
void SoundDevicePort::setId(const QString &id)
{
if (id != m_id) {
m_id = id;
Q_EMIT idChanged(id);
}
}
void SoundDevicePort::setName(const QString &name)
{
if (name != m_name) {
m_name = name;
Q_EMIT nameChanged(name);
}
}
void SoundDevicePort::setCardName(const QString &cardName)
{
if (cardName != m_cardName) {
m_cardName = cardName;
Q_EMIT cardNameChanged(cardName);
}
}
void SoundDevicePort::setIsActive(bool isActive)
{
if (isActive != m_isActive) {
m_isActive = isActive;
Q_EMIT isActiveChanged(isActive);
}
}
void SoundDevicePort::setDirection(const Direction &direction)
{
if (direction != m_direction) {
m_direction = direction;
Q_EMIT directionChanged(direction);
}
}
void SoundDevicePort::setCardId(const uint &cardId)
{
if (cardId != m_cardId) {
m_cardId = cardId;
Q_EMIT cardIdChanged(cardId);
}
}

View File

@ -0,0 +1,76 @@
/*
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
*
* Author: donghualin <donghualin@uniontech.com>
*
* Maintainer: donghualin <donghualin@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SOUNDDEVICEPORT_H
#define SOUNDDEVICEPORT_H
#include <QObject>
class SoundDevicePort : public QObject
{
Q_OBJECT
public:
enum Direction {
Out = 1,
In = 2
};
explicit SoundDevicePort(QObject *parent = nullptr);
virtual ~SoundDevicePort();
inline QString id() const { return m_id; }
void setId(const QString &id);
inline QString name() const { return m_name; }
void setName(const QString &name);
inline QString cardName() const { return m_cardName; }
void setCardName(const QString &cardName);
inline bool isActive() const { return m_isActive; }
void setIsActive(bool isActive);
inline Direction direction() const { return m_direction; }
void setDirection(const Direction &direction);
inline uint cardId() const { return m_cardId; }
void setCardId(const uint &cardId);
Q_SIGNALS:
void idChanged(const QString &id) const;
void nameChanged(const QString &name) const;
void cardNameChanged(const QString &name) const;
void isActiveChanged(bool ative) const;
void directionChanged(Direction direction) const;
void cardIdChanged(uint cardId) const;
private:
QString m_id;
QString m_name;
uint m_cardId;
QString m_cardName;
bool m_isActive;
Direction m_direction;
};
Q_DECLARE_METATYPE(const SoundDevicePort *)
#endif // SOUNDDEVICEPORT_H

View File

@ -23,6 +23,7 @@
#include "settingdelegate.h"
#include "imageutil.h"
#include "slidercontainer.h"
#include "sounddeviceport.h"
#include <DListView>
#include <DPushButton>
@ -47,7 +48,7 @@ DWIDGET_USE_NAMESPACE
#define AUDIOPORT 0
#define AUDIOSETTING 1
const int cardIdRole = itemFlagRole + 1;
const int sortRole = itemFlagRole + 1;
SoundDevicesWidget::SoundDevicesWidget(QWidget *parent)
: QWidget(parent)
@ -55,10 +56,11 @@ SoundDevicesWidget::SoundDevicesWidget(QWidget *parent)
, m_sliderContainer(new SliderContainer(m_sliderParent))
, m_descriptionLabel(new QLabel(tr("Output Device"), this))
, m_deviceList(new DListView(this))
, m_volumeModel(new DBusAudio("org.deepin.daemon.Audio1", "/org/deepin/daemon/Audio1", QDBusConnection::sessionBus(), this))
, m_audioSink(new DBusSink("org.deepin.daemon.Audio1", m_volumeModel->defaultSink().path(), QDBusConnection::sessionBus(), this))
, m_soundInter(new DBusAudio("org.deepin.daemon.Audio1", "/org/deepin/daemon/Audio1", QDBusConnection::sessionBus(), this))
, m_sinkInter(new DBusSink("org.deepin.daemon.Audio1", m_soundInter->defaultSink().path(), QDBusConnection::sessionBus(), this))
, m_model(new QStandardItemModel(this))
, m_delegate(new SettingDelegate(m_deviceList))
, m_lastPort(nullptr)
{
initUi();
initConnection();
@ -132,32 +134,9 @@ void SoundDevicesWidget::initUi()
m_deviceList->setSpacing(10);
m_deviceList->setItemDelegate(m_delegate);
}
void SoundDevicesWidget::onAudioDevicesChanged()
{
QList<AudioPort> ports = m_audioSink->ports();
for (AudioPort port : ports) {
if (port.availability != 0 && port.availability != 2)
continue;
uint cardId = audioPortCardId(port);
if (!m_volumeModel->IsPortEnabled(cardId, port.name))
continue;
DStandardItem *item = new DStandardItem;
item->setText(QString("%1(%2)").arg(port.description).arg(port.name));
item->setIcon(QIcon(soundIconFile(port)));
item->setFlags(Qt::NoItemFlags);
item->setData(port.availability == 2, itemCheckRole);
item->setData(QVariant::fromValue(port), itemDataRole);
item->setData(AUDIOPORT, itemFlagRole);
item->setData(cardId, cardIdRole);
m_model->appendRow(item);
if (port.availability == 2)
m_deviceList->setCurrentIndex(m_model->indexFromItem(item));
}
m_model->setSortRole(sortRole);
// 增加音量设置
DStandardItem *settingItem = new DStandardItem;
settingItem->setText(tr("Sound settings"));
settingItem->setFlags(Qt::NoItemFlags);
@ -166,22 +145,202 @@ void SoundDevicesWidget::onAudioDevicesChanged()
m_model->appendRow(settingItem);
}
void SoundDevicesWidget::onAudioDevicesChanged()
{
QMap<uint, QStringList> tmpCardIds;
const QString cards = m_soundInter->cardsWithoutUnavailable();
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 ) {
const QString portId = jPort["Name"].toString();
const QString portName = jPort["Description"].toString();
SoundDevicePort *port = findPort(portId, cardId);
bool includePort = (port != nullptr);
if (!port)
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 (!includePort)
startAddPort(port);
tmpPorts << portId;
}
}
tmpCardIds.insert(cardId, tmpPorts);
}
onDefaultSinkChanged(m_soundInter->defaultSink());//重新获取切换的设备信息
for (SoundDevicePort *port : m_ports) {
//只要有一个设备在控制中心被禁用后,在任务栏声音设备列表中该设备会被移除,
if (!m_soundInter->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();
}
void SoundDevicesWidget::initConnection()
{
connect(m_audioSink, &DBusSink::VolumeChanged, this, [ = ](double value) { m_sliderContainer->updateSliderValue(value * 100); });
connect(m_volumeModel, &DBusAudio::DefaultSinkChanged, this, &SoundDevicesWidget::onDefaultSinkChanged);
connect(m_sinkInter, &DBusSink::VolumeChanged, this, [ = ](double value) { m_sliderContainer->updateSliderValue(value * 100); });
connect(m_sinkInter, &DBusSink::MuteChanged, this, [ = ] { m_sliderContainer->updateSliderValue(m_sinkInter->volume() * 100); });
connect(m_soundInter, &DBusAudio::DefaultSinkChanged, this, &SoundDevicesWidget::onDefaultSinkChanged);
connect(m_delegate, &SettingDelegate::selectIndexChanged, this, &SoundDevicesWidget::onSelectIndexChanged);
connect(m_volumeModel, &DBusAudio::PortEnabledChanged, this, &SoundDevicesWidget::onAudioDevicesChanged);
connect(m_volumeModel, &DBusAudio::CardsWithoutUnavailableChanged, this, &SoundDevicesWidget::onAudioDevicesChanged);
connect(m_soundInter, &DBusAudio::PortEnabledChanged, this, &SoundDevicesWidget::onAudioDevicesChanged);
connect(m_soundInter, &DBusAudio::CardsWithoutUnavailableChanged, this, &SoundDevicesWidget::onAudioDevicesChanged);
connect(m_sliderContainer, &SliderContainer::sliderValueChanged, this, [ this ](int value) {
m_audioSink->SetVolume(value * 0.01, true);
m_sinkInter->SetVolume(value * 0.01, true);
});
}
/**
* @brief SoundApplet::startAddPort
* @param port
*/
void SoundDevicesWidget::startAddPort(SoundDevicePort *port)
{
if (findPort(port->id(), port->cardId()))
return;
if (port->direction() == SoundDevicePort::Out) {
m_ports.append(port);
addPort(port);
}
}
void SoundDevicesWidget::startRemovePort(const QString &portId, const uint &cardId)
{
SoundDevicePort *port = findPort(portId, cardId);
if (port) {
m_ports.removeOne(port);
port->deleteLater();
removePort(portId, cardId);
}
}
void SoundDevicesWidget::addPort(const SoundDevicePort *port)
{
DStandardItem *portItem = new DStandardItem;
QString deviceName = port->name() + "(" + port->cardName() + ")";
portItem->setIcon(QIcon(soundIconFile()));
portItem->setText(deviceName);
portItem->setTextColorRole(QPalette::BrightText);
portItem->setData(QVariant::fromValue<const SoundDevicePort *>(port), itemDataRole);
portItem->setData(port->isActive(), itemCheckRole);
portItem->setData(AUDIOPORT, itemFlagRole);
connect(port, &SoundDevicePort::nameChanged, this, [ = ](const QString &str) {
QString devName = str + "(" + port->cardName() + ")";
portItem->setText(devName);
});
connect(port, &SoundDevicePort::cardNameChanged, this, [ = ](const QString &str) {
QString devName = port->name() + "(" + str + ")";
portItem->setText(devName);
});
connect(port, &SoundDevicePort::isActiveChanged, this, [ = ](bool isActive) {
portItem->setCheckState(isActive ? Qt::CheckState::Checked : Qt::CheckState::Unchecked);
});
if (port->isActive()) {
portItem->setCheckState(Qt::CheckState::Checked);
}
m_model->appendRow(portItem);
// 遍历列表,依次对不同的设备排序
int row = 0;
int rowCount = m_model->rowCount();
for (int i = 0; i < rowCount; i++) {
QStandardItem *item = m_model->item(i);
if (item->data(itemFlagRole).toInt() == AUDIOSETTING) {
item->setData(rowCount - 1, sortRole);
} else {
item->setData(row, sortRole);
row++;
}
}
m_model->sort(0);
}
void SoundDevicesWidget::removePort(const QString &portId, const uint &cardId)
{
int removeRow = -1;
for (int i = 0; i < m_model->rowCount(); i++) {
QStandardItem *item = m_model->item(i);
if (item->data(itemFlagRole).toInt() != AUDIOPORT)
continue;
const SoundDevicePort *port = item->data(itemDataRole).value<const SoundDevicePort *>();
if (port && port->id() == portId && cardId == port->cardId()) {
removeRow = i;
break;
}
}
if (removeRow >= 0)
m_model->removeRow(removeRow);
}
void SoundDevicesWidget::activePort(const QString &portId, const uint &cardId)
{
for (SoundDevicePort *it : m_ports)
it->setIsActive(it->id() == portId && it->cardId() == cardId);
}
void SoundDevicesWidget::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";
}
}
void SoundDevicesWidget::removeDisabledDevice(QString portId, unsigned int cardId)
{
startRemovePort(portId, cardId);
if (m_sinkInter->activePort().name == portId && m_sinkInter->card() == cardId) {
for (SoundDevicePort *port : m_ports)
port->setIsActive(false);
}
}
QString SoundDevicesWidget::leftIcon()
{
QString iconLeft = QString(":/icons/resources/audio-volume-%1").arg(m_audioSink->mute() ? "muted" : "low");
QString iconLeft = QString(":/icons/resources/audio-volume-%1").arg(m_sinkInter->mute() ? "muted" : "low");
if (DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::LightType)
iconLeft.append("-dark");
@ -197,7 +356,7 @@ QString SoundDevicesWidget::rightIcon()
return iconRight;
}
const QString SoundDevicesWidget::soundIconFile(const AudioPort port) const
const QString SoundDevicesWidget::soundIconFile() const
{
if (DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::LightType)
return QString(":/icons/resources/ICON_Device_Laptop_dark.svg");
@ -217,12 +376,13 @@ void SoundDevicesWidget::resizeHeight()
void SoundDevicesWidget::resetVolumeInfo()
{
m_sliderContainer->updateSliderValue(m_audioSink->volume() * 100);
//无声卡状态下会有伪sink设备显示音量为0
m_sliderContainer->updateSliderValue(findPort(m_sinkInter->activePort().name, m_sinkInter->card()) != nullptr ? m_sinkInter->volume() * 100 : 0);
}
uint SoundDevicesWidget::audioPortCardId(const AudioPort &audioport) const
{
QString cards = m_volumeModel->cardsWithoutUnavailable();
QString cards = m_soundInter->cardsWithoutUnavailable();
QJsonParseError error;
QJsonDocument json = QJsonDocument::fromJson(cards.toLocal8Bit(), &error);
if (error.error != QJsonParseError::NoError)
@ -250,15 +410,28 @@ uint SoundDevicesWidget::audioPortCardId(const AudioPort &audioport) const
return -1;
}
SoundDevicePort *SoundDevicesWidget::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 SoundDevicesWidget::onSelectIndexChanged(const QModelIndex &index)
{
int flag = index.data(itemFlagRole).toInt();
if (flag == AUDIOPORT) {
// 如果是点击具体的声音设备
AudioPort port = index.data(itemDataRole).value<AudioPort>();
uint cardId = index.data(cardIdRole).toUInt();
if (cardId >= 0) {
m_volumeModel->SetPort(cardId, port.name, 1);
const SoundDevicePort *port = m_model->data(index, itemDataRole).value<const SoundDevicePort *>();
if (port) {
m_soundInter->SetPort(port->cardId(), port->id(), int(port->direction()));
//手动勾选时启用设备
m_soundInter->SetPortEnabled(port->cardId(), port->id(), true);
m_deviceList->update();
}
} else {
@ -273,9 +446,27 @@ void SoundDevicesWidget::onSelectIndexChanged(const QModelIndex &index)
void SoundDevicesWidget::onDefaultSinkChanged(const QDBusObjectPath &value)
{
delete m_audioSink;
m_audioSink = new DBusSink("org.deepin.daemon.Audio1", m_volumeModel->defaultSink().path(), QDBusConnection::sessionBus(), this);
connect(m_audioSink, &DBusSink::VolumeChanged, m_sliderContainer, &SliderContainer::updateSliderValue);
delete m_sinkInter;
m_sinkInter = new DBusSink("org.deepin.daemon.Audio1", m_soundInter->defaultSink().path(), QDBusConnection::sessionBus(), this);
connect(m_sinkInter, &DBusSink::VolumeChanged, this, [ = ](double value) { m_sliderContainer->updateSliderValue(value * 100); });
connect(m_sinkInter, &DBusSink::MuteChanged, this, [ = ] { m_sliderContainer->updateSliderValue(m_sinkInter->volume() * 100); });
QString portId = m_sinkInter->activePort().name;
uint cardId = m_sinkInter->card();
//最后一个设备会被移除,但是当在控制中心选中此设备后需要添加,并勾选
if (m_lastPort && m_lastPort->cardId() == cardId && m_lastPort->id() == portId)
startAddPort(m_lastPort);
activePort(portId, cardId);
for (int i = 0; i < m_model->rowCount() ; i++) {
QStandardItem *item = m_model->item(i);
if (item->data(itemFlagRole).toInt() != AUDIOPORT)
continue;
const SoundDevicePort *soundPort = item->data(itemDataRole).value<const SoundDevicePort *>();
item->setData((soundPort && soundPort->id() == portId && soundPort->cardId() == cardId), itemCheckRole);
}
resetVolumeInfo();
m_deviceList->update();

View File

@ -38,6 +38,7 @@ class QLabel;
class VolumeModel;
class AudioSink;
class SettingDelegate;
class SoundDevicePort;
using DBusAudio = org::deepin::daemon::Audio1;
using DBusSink = org::deepin::daemon::audio1::Sink;
@ -58,13 +59,25 @@ private:
void initConnection();
QString leftIcon();
QString rightIcon();
const QString soundIconFile(const AudioPort port) const;
const QString soundIconFile() const;
void resizeHeight();
void resetVolumeInfo();
uint audioPortCardId(const AudioPort &audioport) const;
SoundDevicePort *findPort(const QString &portId, const uint &cardId) const;
void startAddPort(SoundDevicePort *port);
void startRemovePort(const QString &portId, const uint &cardId);
void addPort(const SoundDevicePort *port);
void removePort(const QString &portId, const uint &cardId);
void activePort(const QString &portId, const uint &cardId);
void removeLastDevice();
void removeDisabledDevice(QString portId, unsigned int cardId);
private Q_SLOTS:
void onSelectIndexChanged(const QModelIndex &index);
void onDefaultSinkChanged(const QDBusObjectPath & value);
@ -75,10 +88,12 @@ private:
SliderContainer *m_sliderContainer;
QLabel *m_descriptionLabel;
DListView *m_deviceList;
DBusAudio *m_volumeModel;
DBusSink *m_audioSink;
DBusAudio *m_soundInter;
DBusSink *m_sinkInter;
QStandardItemModel *m_model;
SettingDelegate *m_delegate;
QList<SoundDevicePort *> m_ports;
SoundDevicePort *m_lastPort;
};
#endif // VOLUMEDEVICESWIDGET_H

View File

@ -195,7 +195,7 @@ void SoundItem::refreshIcon()
const double volmue = m_applet->volumeValue();
const double maxVolmue = m_applet->maxVolumeValue();
const bool mute = m_applet->existActiveOutputDevice() ? m_sinkInter->mute() : true;
const bool mute = m_applet->existActiveOutputDevice() ? (m_sinkInter && m_sinkInter->mute()) : true;
const Dock::DisplayMode displayMode = Dock::DisplayMode::Efficient;
QString iconString;
@ -241,7 +241,7 @@ void SoundItem::refreshTips(const int volume, const bool force)
if (!force && !m_tipsLabel->isVisible())
return;
const bool mute = m_applet->existActiveOutputDevice() ? m_sinkInter->mute() : true;
const bool mute = m_applet->existActiveOutputDevice() ? (m_sinkInter && m_sinkInter->mute()) : true;
if (mute) {
m_tipsLabel->setText(QString(tr("Mute")));
} else {
@ -260,7 +260,7 @@ QPixmap SoundItem::pixmap(int colorType) const
const double volmue = m_applet->volumeValue();
const double maxVolmue = m_applet->maxVolumeValue();
const bool mute = m_applet->existActiveOutputDevice() ? m_sinkInter->mute() : true;
const bool mute = m_applet->existActiveOutputDevice() ? (m_sinkInter && m_sinkInter->mute()) : true;
QString iconString;
if (displayMode == Dock::Fashion) {

View File

@ -82,15 +82,18 @@ void SoundWidget::initUi()
void SoundWidget::initConnection()
{
connect(m_defaultSink, &DBusSink::VolumeChanged, this, [ this ](double value) {m_sliderContainer->updateSliderValue(std::round(value * 100.00));});
connect(m_defaultSink, &DBusSink::VolumeChanged, this, [ this ](double value) { m_sliderContainer->updateSliderValue(std::round(value * 100.00)); });
connect(m_defaultSink, &DBusSink::MuteChanged, this, [ = ] { m_sliderContainer->updateSliderValue(m_defaultSink->volume() * 100); });
connect(m_dbusAudio, &DBusAudio::DefaultSinkChanged, this, [ this ](const QDBusObjectPath &value) {
if (m_defaultSink)
delete m_defaultSink;
m_defaultSink = new DBusSink("org.deepin.daemon.Audio1", value.path(), QDBusConnection::sessionBus(), this);
connect(m_defaultSink, &DBusSink::VolumeChanged, this, [ this ](double value) { m_sliderContainer->updateSliderValue(std::round(value * 100.00)); });
connect(m_defaultSink, &DBusSink::MuteChanged, this, [ = ] { m_sliderContainer->updateSliderValue(m_defaultSink->volume() * 100); });
m_sliderContainer->updateSliderValue(std::round(m_defaultSink->volume() * 100.00));
connect(m_defaultSink, &DBusSink::VolumeChanged, m_sliderContainer, &SliderContainer::updateSliderValue);
});
connect(m_dbusAudio, &DBusAudio::MaxUIVolumeChanged, this, [ = ] (double maxValue) {