From ec092bb9800df0f49eec50b7b0a1b49438378463 Mon Sep 17 00:00:00 2001 From: donghualin Date: Thu, 24 Nov 2022 08:14:19 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E6=A0=8F=E6=8F=92=E4=BB=B6=E9=9F=B3=E9=87=8F=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E9=94=99=E8=AF=AF=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 音量设备解析错误,没有和控制中心保持一致,参照之前的音量的解析逻辑重新来显示音量的功能即可 Log: Influence: 从任务栏打开音量,进入音量的详情页面,观察是否和控制中心一致 Bug: https://pms.uniontech.com/bug-view-165853.html Change-Id: I39a6b0664ac2adc40f2ea523d8e0693426640ae5 --- plugins/sound/soundapplet.cpp | 99 ++-------- plugins/sound/soundapplet.h | 60 +----- plugins/sound/sounddeviceport.cpp | 80 ++++++++ plugins/sound/sounddeviceport.h | 76 ++++++++ plugins/sound/sounddeviceswidget.cpp | 281 ++++++++++++++++++++++----- plugins/sound/sounddeviceswidget.h | 21 +- plugins/sound/sounditem.cpp | 6 +- plugins/sound/soundwidget.cpp | 7 +- 8 files changed, 446 insertions(+), 184 deletions(-) create mode 100644 plugins/sound/sounddeviceport.cpp create mode 100644 plugins/sound/sounddeviceport.h diff --git a/plugins/sound/soundapplet.cpp b/plugins/sound/soundapplet.cpp index 067b53c3e..af15ed692 100644 --- a/plugins/sound/soundapplet.cpp +++ b/plugins/sound/soundapplet.cpp @@ -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 SoundDevicePort *port = m_listView->model()->data(idx, Qt::WhatsThisPropertyRole).value(); 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(port), Qt::WhatsThisPropertyRole); + pi->setData(QVariant::fromValue(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(); + auto port = item->data(Qt::WhatsThisPropertyRole).value(); 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()); diff --git a/plugins/sound/soundapplet.h b/plugins/sound/soundapplet.h index 95aaa8164..245dc3a86 100644 --- a/plugins/sound/soundapplet.h +++ b/plugins/sound/soundapplet.h @@ -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 m_ports; + QList m_ports; QString m_deviceInfo; - QPointer m_lastPort;//最后一个因为只有一个设备而被直接移除的设备 + QPointer m_lastPort;//最后一个因为只有一个设备而被直接移除的设备 const QGSettings *m_gsettings; }; diff --git a/plugins/sound/sounddeviceport.cpp b/plugins/sound/sounddeviceport.cpp new file mode 100644 index 000000000..ea4d48519 --- /dev/null +++ b/plugins/sound/sounddeviceport.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ +#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); + } +} diff --git a/plugins/sound/sounddeviceport.h b/plugins/sound/sounddeviceport.h new file mode 100644 index 000000000..8a035c6b1 --- /dev/null +++ b/plugins/sound/sounddeviceport.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. + * + * Author: donghualin + * + * Maintainer: donghualin + * + * 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 . + */ +#ifndef SOUNDDEVICEPORT_H +#define SOUNDDEVICEPORT_H + +#include + +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 diff --git a/plugins/sound/sounddeviceswidget.cpp b/plugins/sound/sounddeviceswidget.cpp index 907b25d00..bb4e4850d 100644 --- a/plugins/sound/sounddeviceswidget.cpp +++ b/plugins/sound/sounddeviceswidget.cpp @@ -23,6 +23,7 @@ #include "settingdelegate.h" #include "imageutil.h" #include "slidercontainer.h" +#include "sounddeviceport.h" #include #include @@ -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 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 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(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(); + 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(); - 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(); + 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(); + item->setData((soundPort && soundPort->id() == portId && soundPort->cardId() == cardId), itemCheckRole); + } resetVolumeInfo(); m_deviceList->update(); diff --git a/plugins/sound/sounddeviceswidget.h b/plugins/sound/sounddeviceswidget.h index 776c84487..4ba093554 100644 --- a/plugins/sound/sounddeviceswidget.h +++ b/plugins/sound/sounddeviceswidget.h @@ -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 m_ports; + SoundDevicePort *m_lastPort; }; #endif // VOLUMEDEVICESWIDGET_H diff --git a/plugins/sound/sounditem.cpp b/plugins/sound/sounditem.cpp index cede35e59..4f952d3b8 100644 --- a/plugins/sound/sounditem.cpp +++ b/plugins/sound/sounditem.cpp @@ -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) { diff --git a/plugins/sound/soundwidget.cpp b/plugins/sound/soundwidget.cpp index 0ebdd900a..49528e92d 100644 --- a/plugins/sound/soundwidget.cpp +++ b/plugins/sound/soundwidget.cpp @@ -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) {