/*
 * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd.
 *
 * 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, or (at your option)
 * 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/&gt;.
 *
 */
#include "ukmedia_main_widget.h"
#include <QHBoxLayout>
#include <QHeaderView>
#include <QStringList>
#include <QSpacerItem>
#include <QListView>
#include <QPainter>
#include <QPainterPath>
#include <QScreen>
#include <QProcess>
#include <QApplication>
#include <QSvgRenderer>
#include <QScrollBar>
#include <QtCore/qmath.h>
#include <QDebug>
#include <QFileInfo>
#include <QList>
#include <QFrame>
#include <KWindowEffects>
#include <kwindowsystem.h>
#include <kwindowsystem_export.h>


#define MAINWINDOW_WIDTH 420
#define MAINWINDOW_HEIGHT 476
#define WIDGET_RADIUS 12
#define CONTENTS_MARGINS_WIDTH 0,0,0,0
#define VOLUMELINE_POS 0,140
#define SETTINGLINE_POS 0,424
#define KEYBINDINGS_CUSTOM_SCHEMA "org.ukui.media.sound"
#define KEYBINDINGS_CUSTOM_DIR "/org/ukui/sound/keybindings/"
#define KEY_SOUNDS_SCHEMA   "org.ukui.sound"
#define EVENT_SOUNDS_KEY "event-sounds"
#define MAX_CUSTOM_SHORTCUTS 1000

#define FILENAME_KEY "filename"
#define NAME_KEY "name"

double transparency = 0.8;
typedef enum {
    DEVICE_VOLUME_BUTTON,
    APP_VOLUME_BUTTON
}ButtonType;

ButtonType btnType = DEVICE_VOLUME_BUTTON;
guint appnum = 0;
int app_count = 0;
extern bool isCheckBluetoothInput;
extern DisplayerMode displayMode ;
QString application_name;

UkmediaMainWidget::UkmediaMainWidget(QMainWindow *parent) : QMainWindow(parent)
{
    //初始化系统托盘
    m_pVolumeControl = new UkmediaVolumeControl();

    //初始化gsetting
    initGsettings();
    //初始化界面
    initWidget();
    //初始化托盘图标
    initSystemTrayIcon();
    //Dbus注册
    UkmediaDbusRegister();
    initAlertSound();
    //处理槽函数
    dealSlot();
}

bool UkmediaMainWidget::eventFilter(QObject *obj, QEvent *event)
{
    if (event->type() == QEvent::ActivationChange) {
        if(QApplication::activeWindow() != this) {
            this->hide();
        }
    }
    return QWidget::eventFilter(obj,event);
}

void UkmediaMainWidget::paintEvent(QPaintEvent *event)
{

}

void UkmediaMainWidget::initSystemTrayIcon()
{
    soundSystemTrayIcon = new UkmediaTrayIcon(this);
    ca_context_create(&caContext);
    //为系统托盘图标添加菜单静音和声音首选项
    soundSystemTrayIcon->setToolTip(tr("Output volume control"));
#if (QT_VERSION <= QT_VERSION_CHECK(5,6,1))
    m_pSoundPreferenceAction = new QAction(tr("Sound preference(S)"),this);
#elif (QT_VERSION > QT_VERSION_CHECK(5,6,1))
    m_pSoundPreferenceAction = new QAction(tr("Sound preference(S)"));
#endif
    QString settingsIconStr = "document-page-setup-symbolic";
    QIcon settingsIcon = QIcon::fromTheme(settingsIconStr);
    m_pSoundPreferenceAction->setIcon(settingsIcon);
    soundSystemTrayIcon->setVisible(true);
    int nOutputValue = paVolumeToValue(m_pVolumeControl->getSinkVolume());

    bool outputStatus = m_pVolumeControl->getSinkMute();
    outputVolumeDarkThemeImage(nOutputValue,outputStatus);

    //初始化右键菜单
    systemTrayMenuInit();
}

/*
 * 初始化右键菜单
 */
void UkmediaMainWidget::systemTrayMenuInit()
{
    menu = new QMenu();
    menu->setAttribute(Qt::WA_NoMouseReplay);
    soundSystemTrayIcon->setContextMenu(menu);
    //设置右键菜单
    menu->addAction(m_pSoundPreferenceAction);
}

/*
 * 初始化界面
 */
void UkmediaMainWidget::initWidget()
{
    QWidget::installEventFilter(this);//为这个窗口安装过滤器
    this->setFixedSize(MAINWINDOW_WIDTH,MAINWINDOW_HEIGHT);
    this->setAttribute(Qt::WA_TranslucentBackground,true);  //透明
    this->setMouseTracking(true);
    this->setFocusPolicy(Qt::NoFocus);

    QString platform = QGuiApplication::platformName();
    if(!platform.startsWith(QLatin1String("wayland"),Qt::CaseInsensitive)){
        QPainterPath path;
        auto rect = this->rect();
        path.addRoundedRect(rect, WIDGET_RADIUS, WIDGET_RADIUS);
        KWindowEffects::enableBlurBehind(this->winId(), true, QRegion(path.toFillPolygon().toPolygon()));   // 背景模糊
    }

    osdWidget = new UkmediaOsdDisplayWidget();
    headsetWidget = new UkuiMediaSetHeadsetWidget;  // osd弹窗

    m_pTabWidget = new QTabWidget(this);
    this->setCentralWidget(m_pTabWidget);
    m_pTabWidget->tabBar()->setFixedWidth(this->width()+1);
    systemWidget = new UkmediaSystemVolumeWidget(m_pTabWidget);
    appWidget = new ApplicationVolumeWidget(m_pTabWidget);

    volumeLine = new Divider(this);
    volumeSettingLine = new Divider(this);
    volumeLine->move(VOLUMELINE_POS);
    volumeSettingLine->move(SETTINGLINE_POS);

    m_pTabWidget->addTab(systemWidget, tr(""));
    m_pTabWidget->addTab(appWidget,tr(""));
    m_tabBarLayout = new QHBoxLayout(this);
    m_tabBarLayout->setContentsMargins(CONTENTS_MARGINS_WIDTH);
    systemWidgetLabel = new QLabel(tr("System Volume"));
    systemWidgetLabel->setAlignment(Qt::AlignCenter);
    appWidgetLabel = new QLabel(tr("App Volume"));
    appWidgetLabel->setAlignment(Qt::AlignCenter);
    m_tabBarLayout->addWidget(systemWidgetLabel);
    m_tabBarLayout->addWidget(appWidgetLabel);
    m_pTabWidget->tabBar()->setLayout(m_tabBarLayout);
    m_pTabWidget->tabBar()->setProperty("setRadius", WIDGET_RADIUS);    // tabbar界面内圆角
    m_pTabWidget->tabBar()->setProperty("useTabbarSeparateLine",false); // 去掉标签页中间的分隔线
    m_pTabWidget->setAttribute(Qt::WA_TranslucentBackground,true);      // 背景透明 解决切换黑屏问题
    paintWithTrans();
}

void UkmediaMainWidget::onTransChanged()
{
    m_pTransparency = m_pTransGsettings->get("transparency").toDouble() + 0.15;
    m_pTransparency = (m_pTransparency > 1) ? 1 : m_pTransparency;
    paintWithTrans();
}

void UkmediaMainWidget::paintWithTrans()
{
    QPalette pal = m_pTabWidget->palette();
    QColor color = qApp->palette().base().color();
    color.setAlphaF(m_pTransparency);
    pal.setColor(QPalette::Base, color);
    m_pTabWidget->setPalette(pal);

    QPalette tabPal = m_pTabWidget->tabBar()->palette();
    tabPal.setColor(QPalette::Base, color);

    QColor inactiveColor = qApp->palette().window().color();
    inactiveColor.setAlphaF(0.86 *m_pTransparency);
    tabPal.setColor(QPalette::Window, inactiveColor);

    m_pTabWidget->tabBar()->setPalette(tabPal);
}

/*
 * 添加分隔线
 */
void UkmediaMainWidget::myLine(QFrame *volumeLine,QFrame *volumeSettingLine)
{
    volumeLine = new QFrame(this);
    volumeLine->setFrameShape(QFrame::NoFrame);
    volumeLine->setFrameStyle(QFrame::HLine);
    volumeLine->setFixedSize(420,1);
    volumeLine->setParent(this);
    QPalette palette = volumeLine->palette();
    QColor color = QColor(239,239,239);
    color.setAlphaF(0.1);
    palette.setColor(QPalette::WindowText, color);
    volumeLine->setPalette(palette);

    volumeSettingLine = new QFrame(this);
    volumeSettingLine->setFrameShape(QFrame::NoFrame);
    volumeSettingLine->setFrameStyle(QFrame::HLine);
    volumeSettingLine->setFixedSize(420,1);
    volumeSettingLine->setParent(this);
    palette = volumeSettingLine->palette();
    palette.setColor(QPalette::WindowText, color);
    volumeSettingLine->setPalette(palette);

    volumeLine->move(0,140);
    volumeSettingLine->move(0,424);
}

/*
 * 初始化静音灯
 */
void UkmediaMainWidget::initVolumeLed()
{
    bool outputStatus = m_pVolumeControl->getSinkMute();//获取输出设备的静音状态
    if(outputStatus) {
        QDBusMessage message =QDBusMessage::createSignal("/","org.ukui.media","systemOutputVolumeIsMute");
        message << "mute";
        QDBusConnection::systemBus().send(message);
    }
    else {
        QDBusMessage message =QDBusMessage::createSignal("/","org.ukui.media","systemOutputVolumeIsMute");
        message << "no";
        QDBusConnection::systemBus().send(message);
    }
    themeChangeIcons();
}


/*
 * 注册dbus
 */
void UkmediaMainWidget::UkmediaDbusRegister()
{
    QDBusConnection::sessionBus().unregisterService("org.ukui.media");
    QDBusConnection::sessionBus().registerService("org.ukui.media");
    QDBusConnection::sessionBus().registerObject("/", this,QDBusConnection :: ExportAllSlots | QDBusConnection :: ExportAllSignals);
}


void UkmediaMainWidget::initVolumeSlider()
{
    if(isFirstMuteLed)
    {
        initVolumeLed();
        isFirstMuteLed = false;
    }
    initDefaultSinkVolume();
    initDefaultSourceVolume();
    resetVolumeSliderRange();

    int sinkVolume = paVolumeToValue(m_pVolumeControl->getSinkVolume());
    QString percent;
    percent = QString::number(sinkVolume);
    appWidget->systemVolumeDisplayLabel->setText(percent+"%");
    systemWidget->m_pSystemVolumeSliderLabel->setText(percent+"%");
    appWidget->systemVolumeSlider->blockSignals(true);
    systemWidget->m_pSystemVolumeSlider->blockSignals(true);
    systemWidget->m_pSystemVolumeSlider->setValue(sinkVolume);
    appWidget->systemVolumeSlider->setValue(sinkVolume);
    systemWidget->m_pSystemVolumeSlider->blockSignals(false);
    appWidget->systemVolumeSlider->blockSignals(false);

    initOutputListWidgetItem();
    initInputListWidgetItem();
    themeChangeIcons();
    //设置输入输出设备名
}

/*
 * 初始化默认音量
 */
void UkmediaMainWidget::initDefaultSinkVolume()
{
    qDebug() << "initDefaultSinkVolume----" << m_pVolumeControl->sinkIndex << m_pVolumeControl->sinkPortName;

    int volume;
    QString temp = "";
    QString outputCardName = findCardName(m_pVolumeControl->defaultOutputCard,m_pVolumeControl->cardMap);

    if (m_pVolumeControl->sinkPortName.contains("histen-algo",Qt::CaseInsensitive)) {
        m_pVolumeControl->sinkPortName = m_pVolumeControl->findSinkActivePortName(PANGUW_SINK);
        temp = "histen-algo";
    }

    if(m_pVolumeControl->sinkPortName != "" && !m_pVolumeControl->customSoundFile->isExist(stringRemoveUnrecignizedChar(m_pVolumeControl->sinkPortName)))
    {
        if (m_pVolumeControl->sinkPortName.contains(HEADPHONE,Qt::CaseInsensitive)) {
            volume = HEADPHONE_VOLUME;
        }
        else if (m_pVolumeControl->sinkPortName.contains(HDMI,Qt::CaseInsensitive)) {
            volume = HDMI_VOLUME;
        }
        else if (m_pVolumeControl->sinkPortName.contains(SPEAKER,Qt::CaseInsensitive)){
            volume = OUTPUT_VOLUME;
        }
        else {
            volume = HEADPHONE_VOLUME;
        }
        if(outputCardName.contains(BLUEZ,Qt::CaseInsensitive))
            volume = OUTPUT_VOLUME;
        m_pVolumeControl->setSinkVolume(m_pVolumeControl->sinkIndex,volume);
        m_pVolumeControl->customSoundFile->addXmlNode(m_pVolumeControl->sinkPortName,false);
        qDebug() << "初始化输出音量为:" << volume ;
        if (temp != "")
            m_pVolumeControl->sinkPortName = temp;
    }

    else if(m_pVolumeControl->sinkPortName == "" && !m_pVolumeControl->customSoundFile->isExist(stringRemoveUnrecignizedChar(m_pVolumeControl->defaultSinkName)))
    {
        volume = OUTPUT_VOLUME;
        m_pVolumeControl->setSinkVolume(m_pVolumeControl->sinkIndex,volume);
        m_pVolumeControl->customSoundFile->addXmlNode(m_pVolumeControl->defaultSinkName,false);
        qDebug()<< "初始化音量SinkPortName不存在的情况" << volume;
    }
}

void UkmediaMainWidget::initDefaultSourceVolume()
{
    qDebug() << "initDefaultSourceVolume-----" << m_pVolumeControl->sourceIndex << m_pVolumeControl->sourcePortName;

    if(m_pVolumeControl->sourcePortName == "" && !m_pVolumeControl->customSoundFile->isExist(stringRemoveUnrecignizedChar(m_pVolumeControl->defaultSourceName)))
    {
        m_pVolumeControl->customSoundFile->addXmlNode(m_pVolumeControl->defaultSourceName,false);
        m_pVolumeControl->setSourceVolume(m_pVolumeControl->sourceIndex,MIC_VOLUME);
        qDebug()<< "初始化音量SourcePortName不存在的情况" <<m_pVolumeControl->defaultSourceName ;
    }

    else if(m_pVolumeControl->sourcePortName != "" && !m_pVolumeControl->customSoundFile->isExist(stringRemoveUnrecignizedChar(m_pVolumeControl->sourcePortName)))
    {
        m_pVolumeControl->customSoundFile->addXmlNode(m_pVolumeControl->sourcePortName,false);
        m_pVolumeControl->setSourceVolume(m_pVolumeControl->sourceIndex,MIC_VOLUME);
        qDebug() << "初始化输入音量为100" ;
    }
}

/*
 * 初始化output/input list widget的选项
 */
void UkmediaMainWidget::initOutputListWidgetItem()
{
    QString outputCardName = findCardName(m_pVolumeControl->defaultOutputCard,m_pVolumeControl->cardMap);
    QString outputPortLabel = findOutputPortLabel(m_pVolumeControl->defaultOutputCard,m_pVolumeControl->sinkPortName);
    findOutputListWidgetItem(outputCardName,outputPortLabel);

    int vol = m_pVolumeControl->getSinkVolume();
    systemWidget->m_pSystemVolumeSlider->blockSignals(true);
    appWidget->systemVolumeSlider->blockSignals(true);
    appWidget->systemVolumeSlider->setValue(paVolumeToValue(vol));
    systemWidget->m_pSystemVolumeSlider->setValue(paVolumeToValue(vol));
    systemWidget->m_pSystemVolumeSlider->blockSignals(false);
    appWidget->systemVolumeSlider->blockSignals(false);
    systemWidget->m_pSystemVolumeSliderLabel->setText(QString::number(paVolumeToValue(vol))+"%");
    appWidget->systemVolumeDisplayLabel->setText(QString::number(paVolumeToValue(vol))+"%");

    outputListWidgetRow = systemWidget->m_pOutputListWidget->currentRow();

    qDebug() <<"initOutputListWidgetItem" << m_pVolumeControl->defaultOutputCard << outputCardName
            <<m_pVolumeControl->sinkPortName << outputPortLabel;
}

void UkmediaMainWidget::initInputListWidgetItem()
{
    QString inputCardName = findCardName(m_pVolumeControl->defaultInputCard,m_pVolumeControl->cardMap);
    QString inputPortLabel = findInputPortLabel(m_pVolumeControl->defaultInputCard,m_pVolumeControl->sourcePortName);
    findInputListWidgetItem(inputCardName,inputPortLabel);

    qDebug() <<"initInputListWidgetItem" << m_pVolumeControl->defaultInputCard << inputCardName
            <<m_pVolumeControl->sourcePortName << inputPortLabel;
}

/*
 * 滑动条值转换成音量值
 */
int UkmediaMainWidget::valueToPaVolume(int value)
{
    return value / UKMEDIA_VOLUME_NORMAL * PA_VOLUME_NORMAL;
}

/*
 * 音量值转换成滑动条值
 */
int UkmediaMainWidget::paVolumeToValue(int value)
{
    return (value / PA_VOLUME_NORMAL * UKMEDIA_VOLUME_NORMAL) + 0.5;
}

QString UkmediaMainWidget::outputVolumeToIconStr(bool status,int volume)
{
    QString iconStr;
    if (status) {
        iconStr = iconNameOutputs[0];
    }
    else if (volume <= 0 && !shortcutMute) {
        iconStr = iconNameOutputs[0];
    }
    else if(volume <= 0 && shortcutMute){
        iconStr = iconNameOutputs[0];
    }
    else if (volume > 0 && volume <= 33) {
        iconStr = iconNameOutputs[1];
    }
    else if (volume >33 && volume <= 66) {
        iconStr = iconNameOutputs[2];
    }
    else {
        iconStr = iconNameOutputs[3];
    }
    return iconStr;
}

/*
 * 处理槽函数
 */
void UkmediaMainWidget::dealSlot()
{
    QDBusInterface *iface = new QDBusInterface("org.freedesktop.login1",
                                               "/org/freedesktop/login1",
                                               "org.freedesktop.login1.Manager",
                                               QDBusConnection::systemBus(),
                                               this);
    connect(iface, SIGNAL(PrepareForSleep(bool)), this, SLOT(onPrepareForSleep(bool)));

    //根据设备检测发来的信号，显示相应的提示窗
    connect(m_pVolumeControl,SIGNAL(device_changed_signal(QString)),this,SLOT(deviceChangedShowSlot(QString)));

    //声卡包含headsetmic 端口时插入4段式mic需要设置对应的port
    QDBusConnection::sessionBus().connect( QString(), "/", "org.ukui.media", "headsetJack", this, SLOT(setHeadsetPort(QString)));
    QTimer::singleShot(100, this, SLOT(initVolumeSlider()));

    connect(m_pVolumeControl,&UkmediaVolumeControl::updateMute,this,[=](bool state) {
            bool outputStatus = m_pVolumeControl->getSinkMute();//获取输出设备的静音状态
            if(outputStatus) {
                QDBusMessage message =QDBusMessage::createSignal("/","org.ukui.media","systemOutputVolumeIsMute");
                message << "mute";
                QDBusConnection::systemBus().send(message);
            }
            else {
                QDBusMessage message =QDBusMessage::createSignal("/","org.ukui.media","systemOutputVolumeIsMute");
                message << "no";
                QDBusConnection::systemBus().send(message);
            }
            setVolumeSettingMute(state);
            themeChangeIcons();
        });

        connect(m_pVolumeControl,&UkmediaVolumeControl::updateSourceMute,this,[=](bool state) {
            bool inputStatus = m_pVolumeControl->getSourceMute();//获取输入设备的静音状态
            if(inputStatus) {
                QDBusMessage message =QDBusMessage::createSignal("/","org.ukui.media","systemInputVolumeIsMute");
                message << "mute";
                QDBusConnection::systemBus().send(message);
            }
            else {
                QDBusMessage message =QDBusMessage::createSignal("/","org.ukui.media","systemInputVolumeIsMute");
                message << "no";
                QDBusConnection::systemBus().send(message);
            }
            themeChangeIcons();
        });

    connect(m_pVolumeControl,&UkmediaVolumeControl::updateVolume,this,[=](int value){

        bool outputStatus = m_pVolumeControl->getSinkMute();
        qDebug() << "UpdateSinkVolume" << value << paVolumeToValue(value) << outputStatus;
        QString percent;
        percent = QString::number(paVolumeToValue(value));

        //设置调节输入音量的提示音
        const gchar *id = NULL;
        const gchar *desc = NULL;
        gint retval;

        QList<char *> existsPath = listExistsPath();
        QString filenameStr;
        for (char * path : existsPath) {

            char * prepath = QString(KEYBINDINGS_CUSTOM_DIR).toLatin1().data();
            char * allpath = strcat(prepath, path);

            const QByteArray ba(KEYBINDINGS_CUSTOM_SCHEMA);
            const QByteArray bba(allpath);
            if(QGSettings::isSchemaInstalled(ba))
            {
                QGSettings * settings = new QGSettings(ba, bba);
                filenameStr = settings->get(FILENAME_KEY).toString();
                QString nameStr = settings->get(NAME_KEY).toString();
                if (nameStr == "volume-changed") {
                    break;
                }
            }
        }
        const QByteArray text = filenameStr.toLocal8Bit();
        id = text.data();
        desc = "Volume Changed";
        const gchar *eventId =id;
        if (QGSettings::isSchemaInstalled(KEY_SOUNDS_SCHEMA)){
            if (m_pSoundSettings->keys().contains("eventSounds")) {
                bool alertStatus = m_pSoundSettings->get(EVENT_SOUNDS_KEY).toBool();
                if (alertStatus) {
                    m_pTimer->start(100);
                }
            }
        }

        appWidget->systemVolumeDisplayLabel->setText(percent+"%");
        systemWidget->m_pSystemVolumeSliderLabel->setText(percent+"%");
        appWidget->systemVolumeSlider->blockSignals(true);
        systemWidget->m_pSystemVolumeSlider->blockSignals(true);
        systemWidget->m_pSystemVolumeSlider->setValue(paVolumeToValue(value));
        appWidget->systemVolumeSlider->setValue(paVolumeToValue(value));
        systemWidget->m_pSystemVolumeSlider->blockSignals(false);
        appWidget->systemVolumeSlider->blockSignals(false);
        setVolumeSettingMute(outputStatus);
        setVolumeSettingValue(paVolumeToValue(value));
        initOutputListWidgetItem();
        themeChangeIcons();
    });

    connect(m_pVolumeControl,&UkmediaVolumeControl::updateSourceVolume,this,[=](int value){
        bool inputStatus = m_pVolumeControl->getSourceMute();
        qDebug() << "UpdateSourceVolume:" << value << paVolumeToValue(value) << inputStatus;
        initInputListWidgetItem();
        themeChangeIcons();
    });

    connect(m_pVolumeControl,SIGNAL(addSinkInputSignal(const gchar *,const gchar*,int,int,int)),this,SLOT(addAppToAppwidget(const gchar*,const gchar *,int,int,int)));
    connect(m_pVolumeControl,SIGNAL(sinkInputVolumeChangedSignal(const gchar *,const gchar*,int)),this,SLOT(sinkInputVolumeChangedSlot(const gchar*,const gchar *,int)));
    connect(m_pVolumeControl,SIGNAL(removeSinkInputSignal(const gchar *)),this,SLOT(removeSubAppWidget(const gchar*)));
    connect(m_pVolumeControl,SIGNAL(deviceChangedSignal()),this,SLOT(updateListWidgetItemSlot()));
    QDBusConnection::sessionBus().connect( QString(), "/", "org.kylin.music", "sinkInputVolumeChanged", this, SLOT(updateAppVolume(QString,int,bool)));
    QDBusConnection::sessionBus().connect( QString(), "/", "org.kylin.video", "sinkInputVolumeChanged", this, SLOT(updateAppVolume(QString,int,bool)));

    connect(systemWidget->m_pOutputListWidget,&QListWidget::itemClicked,this,[=](){
        if(outputListWidgetRow != systemWidget->m_pOutputListWidget->currentRow()){
            outputListWidgetCurrentRowChangedSlot(systemWidget->m_pOutputListWidget->currentRow());
            outputListWidgetRow = systemWidget->m_pOutputListWidget->currentRow();
        }
    });

    connect(systemWidget->m_pInputListWidget,SIGNAL(currentRowChanged(int )),this,SLOT(inputListWidgetCurrentRowChangedSlot(int)));


    connect(systemWidget->m_pSystemVolumeSlider,&UkmediaVolumeSlider::silderPressSignal,this,[=](){
        mousePress = true;
        mouseReleaseState = false;
    });
    connect(systemWidget->m_pSystemVolumeSlider,&UkmediaVolumeSlider::silderReleaseSignal,this,[=](){
        mouseReleaseState = true;
    });
    connect(appWidget->systemVolumeSlider,&UkmediaVolumeSlider::silderPressSignal,this,[=](){
        mousePress = true;
        mouseReleaseState = false;
    });
    connect(appWidget->systemVolumeSlider,&UkmediaVolumeSlider::silderReleaseSignal,this,[=](){
        mouseReleaseState = true;
    });

    m_pTimer = new QTimer(this);
    connect(m_pTimer, SIGNAL(timeout()), this, SLOT(handleTimeout()));
    m_pTimer2 = new QTimer(this);
    connect(m_pTimer2, &QTimer::timeout, this, [=](){
        if(mouseReleaseState){
            gint retval;
            const gchar *desc = "Volume Changed";
            QString filenameStr;
            QList<char *> existsPath = this->listExistsPath();
            for (char * path : existsPath) {
                char * prepath = QString(KEYBINDINGS_CUSTOM_DIR).toLatin1().data();
                char * allpath = strcat(prepath, path);
                const QByteArray ba(KEYBINDINGS_CUSTOM_SCHEMA);
                const QByteArray bba(allpath);
                if(QGSettings::isSchemaInstalled(ba))
                {
                    QGSettings * settings = new QGSettings(ba, bba);
                    filenameStr = settings->get(FILENAME_KEY).toString();
                    QString nameStr = settings->get(NAME_KEY).toString();
                    if (nameStr == "volume-changed") {
                        break;
                    }
                }
            }
            const QByteArray text = filenameStr.toLocal8Bit();
            const gchar *id = text.data();
            const gchar *eventId =id;
            if(desc){
                if (QGSettings::isSchemaInstalled(KEY_SOUNDS_SCHEMA)){
                    if (m_pSoundSettings->keys().contains("eventSounds")) {
                        bool status = m_pSoundSettings->get(EVENT_SOUNDS_KEY).toBool();
                        if (status)
                            retval = ca_context_play (this->caContext, 0,
                                                      CA_PROP_EVENT_ID, eventId,
                                                      CA_PROP_EVENT_DESCRIPTION, desc, NULL);
                    }
                }

                qDebug() << "ca_context_play"  << eventId << retval;
            }
            m_pTimer->stop();
            mousePress = false;
            mouseReleaseState = false;
        }
        else{
            m_pTimer2->start(100);
        }
    });

    /*
     * 完整模式下,应用音量界面，当滑动条值改变时更改系统音量
     */
    connect(appWidget->systemVolumeSlider,SIGNAL(valueChanged(int)),this,SLOT( advancedSystemSliderChangedSlot(int)));

    connect(systemWidget->m_pSystemVolumeSlider,SIGNAL(valueChanged(int)),this,SLOT(systemVolumeSliderChangedSlot(int)));

    connect(systemWidget->m_pSystemVolumeBtn,SIGNAL(clicked()),this,SLOT(systemVolumeButtonClickedSlot()));
    connect(appWidget->systemVolumeBtn,SIGNAL(clicked()),this,SLOT(appWidgetMuteButtonCLickedSlot()));

    /*
     * 鼠标中间滚轮键设置音量静音
     */
    connect(this,SIGNAL(mouse_middle_clicked_signal()),this,SLOT(mouseMeddleClickedTraySlot()));
    /*
     * 当无任何控制音量的界面显示时，鼠标滚轮向上滚动音量托盘图标增加音量
     * 向下滚动减少音量值
     */
    connect(soundSystemTrayIcon,SIGNAL(wheelRollEventSignal(bool)),this,SLOT(trayWheelRollEventSlot(bool)));

    connect(soundSystemTrayIcon,SIGNAL(activated(QSystemTrayIcon::ActivationReason)),\
            this,SLOT(activatedSystemTrayIconSlot(QSystemTrayIcon::ActivationReason)));
    connect(m_pSoundPreferenceAction,SIGNAL(triggered()),this,SLOT(jumpControlPanelSlot()));
    connect(m_pVolumeControl,SIGNAL(updatePortSignal()),this,SLOT(updateDevicePort()));

    connect(m_pVolumeControl,SIGNAL(checkDeviceSelectionSianal(const pa_card_info *)),this,SLOT(checkAudioDeviceSelectionNeeded(const pa_card_info *)));

    connect(m_pVolumeControl,&UkmediaVolumeControl::removeSinkSignal,[=](){
        qDebug() << "removre sink signal";
        systemWidget->m_pOutputListWidget->blockSignals(true);
    });
    connect(appWidget->volumeSettingButton,SIGNAL(clicked()),this,SLOT(jumpControlPanelSlot()));
    connect(systemWidget->volumeSettingButton,SIGNAL(clicked()),this,SLOT(jumpControlPanelSlot()));
}

void UkmediaMainWidget::initGsettings()
{
    m_pInitSystemVolumeSetting = new QGSettings(UKUI_AUDIO_SCHEMA);
    //检测系统主题
    if (QGSettings::isSchemaInstalled(UKUI_THEME_SETTING)){
        m_pThemeSetting = new QGSettings(UKUI_THEME_SETTING);
        m_pFontSetting = new QGSettings(UKUI_THEME_SETTING);
        QString fontType;
        if (m_pThemeSetting->keys().contains("styleName")) {
            mThemeName = m_pThemeSetting->get(UKUI_THEME_NAME).toString();
        }
        if (m_pFontSetting->keys().contains("systemFont")) {
            fontType = m_pFontSetting->get("systemFont").toString();
        }
        if (m_pFontSetting->keys().contains("systemFontSize")) {
            int font = m_pFontSetting->get("system-font-size").toInt();
            QFont fontSize(fontType,font);
//            appWidget->systemVolumeLabel->setFont(fontSize);
        }
        connect(m_pFontSetting,SIGNAL(changed(const QString &)),this,SLOT(fontSizeChangedSlot(const QString &)));
        connect(m_pThemeSetting, SIGNAL(changed(const QString &)),this,SLOT(ukuiThemeChangedSlot(const QString &)));
    }
    //获取声音gsettings值
    if (QGSettings::isSchemaInstalled(KEY_SOUNDS_SCHEMA)){
        m_pSoundSettings = new QGSettings(KEY_SOUNDS_SCHEMA);
        if (m_pSoundSettings->keys().contains("dnsNoiseReduction")) {
            QTimer *timer = new QTimer();
            timer->start(1000);
            connect(timer,&QTimer::timeout,[=](){
                switchModuleEchoCancel();
                delete timer;
            });
        }

        connect(m_pSoundSettings, SIGNAL(changed(const QString &)),this,SLOT(soundSettingChanged(const QString &)));
    }
    //获取透明度
    if(QGSettings::isSchemaInstalled(TRANSPARENCY_GSETTINGS)) {
        m_pTransGsettings = new QGSettings(TRANSPARENCY_GSETTINGS);
        if(m_pTransGsettings->keys().contains(QString("transparency"))) {
            m_pTransparency=m_pTransGsettings->get("transparency").toDouble() + 0.15;
            m_pTransparency = (m_pTransparency > 1) ? 1 : m_pTransparency;
            connect(m_pTransGsettings, SIGNAL(changed(const QString &)), this, SLOT(onTransChanged()));
        }
    }

    //给侧边栏提供音量之设置
    if (QGSettings::isSchemaInstalled(UKUI_VOLUME_BRIGHTNESS_GSETTING_ID)) {
        m_pVolumeSetting = new QGSettings(UKUI_VOLUME_BRIGHTNESS_GSETTING_ID);

        connect(m_pVolumeSetting,SIGNAL(changed(const QString &)),this,SLOT(volumeSettingChangedSlot()));
    }

    //如果为第一次运行需要关闭dp对应的配置文件
    if (QGSettings::isSchemaInstalled(UKUI_AUDIO_SCHEMA)){
        m_pInitSystemVolumeSetting = new QGSettings(UKUI_AUDIO_SCHEMA);
        if (m_pInitSystemVolumeSetting->keys().contains("firstRun")) {
            bool isFirstRun = m_pInitSystemVolumeSetting->get(FIRST_RUN).toBool();
            if (isFirstRun) {
                m_pInitSystemVolumeSetting->set(FIRST_RUN,false);
            }
        }
    }

}

/*
 * 更新设备时更新字体(对listwidget的特殊处理)
 */
void UkmediaMainWidget::updateOutputListWidgetFont() {
    QString fontType;
    if (m_pFontSetting->keys().contains("systemFont")) {
        fontType = m_pFontSetting->get("systemFont").toString();
    }
    if (m_pFontSetting->keys().contains("systemFontSize")) {
        int font = m_pFontSetting->get("system-font-size").toInt();
        QFont fontSize(fontType,font);
        for (int row=0;row<systemWidget->m_pOutputListWidget->count();row++) {
            QListWidgetItem *item = systemWidget->m_pOutputListWidget->item(row);
            UkuiListWidgetItem *wid = (UkuiListWidgetItem *)systemWidget->m_pOutputListWidget->itemWidget(item);
            wid->portLabel->setFont(fontSize);
        }
    }
}

void UkmediaMainWidget::initAlertSound()
{
    eventList = new QStringList;
    eventIdNameList = new QStringList;

    eventList->append("window-close");
    eventList->append("system-setting");
    eventList->append("volume-changed");
    eventList->append("alert-sound");
    eventIdNameList->append("gudou");
    eventIdNameList->append("gudou");
    eventIdNameList->append("gudou");
    eventIdNameList->append("gudou");
    for (int i=0;i<eventList->count();i++) {
        //        getValue();
        addValue(eventList->at(i),eventIdNameList->at(i));
    }

    QDomDocument doc("xunguang");
    QString audioPath = "/usr/share/sounds/xunguang.xml";
    QFile file(audioPath);

    if (!file.open(QIODevice::ReadOnly)){
        qDebug()<<"open xunguang.xml failed!!!";
        return;
    }
    if (!doc.setContent(&file)){
        file.close();
        return;
    }
    file.close();

    QDomElement docElem = doc.documentElement();
    QDomNode n = docElem.firstChild();

    while (!n.isNull()){
        QDomElement e = n.toElement();
        QString rootName = n.toElement().tagName();
        QDomNodeList sonList = e.childNodes();
        QDomElement sonElement = sonList.at(0).toElement();
        if (!e.isNull()){
            qDebug() << "add xunguang.xml" << "name" << e.tagName() << "filename" << sonElement.text() << endl;
            eventList->append(e.tagName());
            eventIdNameList->append(sonElement.text());
        }
        n = n.nextSibling();
    }
    for (int i=0;i<eventList->count();i++)
        addValue(eventList->at(i),eventIdNameList->at(i));
}


QList<char *> UkmediaMainWidget::listExistsPath()
{
    char ** childs;
    int len;

    DConfClient * client = dconf_client_new();
    childs = dconf_client_list (client, KEYBINDINGS_CUSTOM_DIR, &len);
    g_object_unref (client);

    QList<char *> vals;

    for (int i = 0; childs[i] != NULL; i++){
        if (dconf_is_rel_dir (childs[i], NULL)){
            char * val = g_strdup (childs[i]);

            vals.append(val);
        }
    }
    g_strfreev (childs);
    return vals;
}

QString UkmediaMainWidget::findFreePath(){
    int i = 0;
    char * dir;
    bool found;
    QList<char *> existsdirs;

    existsdirs = listExistsPath();

    for (; i < MAX_CUSTOM_SHORTCUTS; i++){
        found = true;
        dir = QString("custom%1/").arg(i).toLatin1().data();
        for (int j = 0; j < existsdirs.count(); j++)
            if (!g_strcmp0(dir, existsdirs.at(j))){
                found = false;
                break;
            }
        if (found)
            break;
    }

    if (i == MAX_CUSTOM_SHORTCUTS){
        qDebug() << "Keyboard Shortcuts" << "Too many custom shortcuts";
        return "";
    }

    return QString("%1%2").arg(KEYBINDINGS_CUSTOM_DIR).arg(QString(dir));
}

void UkmediaMainWidget::addValue(QString name,QString filename)
{
    //在创建setting表时，先判断是否存在该设置，存在时不创建
    QList<char *> existsPath = listExistsPath();
    for (char * path : existsPath) {

        char * prepath = QString(KEYBINDINGS_CUSTOM_DIR).toLatin1().data();
        char * allpath = strcat(prepath, path);

        const QByteArray ba(KEYBINDINGS_CUSTOM_SCHEMA);
        const QByteArray bba(allpath);
        if(QGSettings::isSchemaInstalled(ba))
        {
            QGSettings * settings = new QGSettings(ba, bba);
            QString filenameStr = settings->get(FILENAME_KEY).toString();
            QString nameStr = settings->get(NAME_KEY).toString();

            if (nameStr == name) {
                return;
            }
            delete settings;
        }
        else {
            continue;
        }

    }
    QString availablepath = findFreePath();

    const QByteArray id(KEYBINDINGS_CUSTOM_SCHEMA);
    const QByteArray idd(availablepath.toUtf8().data());
    if(QGSettings::isSchemaInstalled(id))
    {
        QGSettings * settings = new QGSettings(id, idd);
        settings->set(FILENAME_KEY, filename);
        settings->set(NAME_KEY, name);
        delete settings;
    }
}

/*
 *  当检测到4段式3.5mm耳机插入时(声卡包含headsetmic端口)
 */
void UkmediaMainWidget::setHeadsetPort(QString str)
{
    qDebug() << "setHeadsetPort " << str << m_pVolumeControl->sinkIndex;
    /*
     *output: headphone
     *input: intel mic
    */
    if (strcmp(str.toLatin1().data(),"headphone") == 0) {
        m_pVolumeControl->setSinkPort(m_pVolumeControl->defaultSinkName,m_pHeadphonesName);
        m_pVolumeControl->setSourcePort(m_pVolumeControl->defaultSourceName,m_pInternalmicName);

            /*
             *当需要设置的输入端口不在同一个sink上时，需要设置默认的输入设备
            */


    } /*output: headphone     input: headset mic*/
    else if (strcmp(str.toLatin1().data(),"headset") == 0) {
        m_pVolumeControl->setSinkPort(m_pVolumeControl->defaultSinkName,m_pHeadphonesName);
        m_pVolumeControl->setSourcePort(m_pVolumeControl->defaultSourceName,m_pHeadsetmicName);
            /*
             *当需要设置的输入端口不在同一个sink上时，需要设置默认的输入设备
            */


    }/*output: speaker     input: headphone mic*/
    else if (strcmp(str.toLatin1().data(),"headphone mic") == 0) {
        m_pVolumeControl->setSinkPort(m_pVolumeControl->defaultSinkName,m_pInternalspkName);
        m_pVolumeControl->setSourcePort(m_pVolumeControl->defaultSourceName,m_pHeadphonemicName);
            /*
             *当需要设置的输入端口不在同一个sink上时，需要设置默认的输入设备
            */

    }
}

/*
 * 音量改变提示：策略是停止滑动时，播放提示声
 */
void UkmediaMainWidget::handleTimeout()
{
    if(mousePress){
        if(mouseReleaseState){
            gint retval;
            const gchar *desc = "Volume Changed";
            QString filenameStr;
            QList<char *> existsPath = this->listExistsPath();
            for (char * path : existsPath) {
                char * prepath = QString(KEYBINDINGS_CUSTOM_DIR).toLatin1().data();
                char * allpath = strcat(prepath, path);
                const QByteArray ba(KEYBINDINGS_CUSTOM_SCHEMA);
                const QByteArray bba(allpath);
                if(QGSettings::isSchemaInstalled(ba))
                {
                    QGSettings * settings = new QGSettings(ba, bba);
                    filenameStr = settings->get(FILENAME_KEY).toString();
                    QString nameStr = settings->get(NAME_KEY).toString();
                    if (nameStr == "volume-changed") {
                        break;
                    }
                }
            }
            const QByteArray text = filenameStr.toLocal8Bit();
            const gchar *id = text.data();
            const gchar *eventId =id;
            if(desc){
                if (QGSettings::isSchemaInstalled(KEY_SOUNDS_SCHEMA)){
                    if (m_pSoundSettings->keys().contains("eventSounds")) {
                        bool status = m_pSoundSettings->get(EVENT_SOUNDS_KEY).toBool();
                        if (status)
                            retval = ca_context_play (this->caContext, 0,
                                                      CA_PROP_EVENT_ID, eventId,
                                                      CA_PROP_EVENT_DESCRIPTION, desc, NULL);
                    }
                }
            }
            m_pTimer->stop();
            mousePress = false;
            mouseReleaseState = false;
        }
        else {
            m_pTimer2->start(50);
        }
        m_pTimer->stop();
    }
    else
    {
        gint retval;
        const gchar *desc = "Volume Changed";
        QString filenameStr;
        QList<char *> existsPath = this->listExistsPath();
        for (char * path : existsPath) {
            char * prepath = QString(KEYBINDINGS_CUSTOM_DIR).toLatin1().data();
            char * allpath = strcat(prepath, path);
            const QByteArray ba(KEYBINDINGS_CUSTOM_SCHEMA);
            const QByteArray bba(allpath);
            if(QGSettings::isSchemaInstalled(ba))
            {
                QGSettings * settings = new QGSettings(ba, bba);
                filenameStr = settings->get(FILENAME_KEY).toString();
                QString nameStr = settings->get(NAME_KEY).toString();
                if (nameStr == "volume-changed") {
                    break;
                }
            }
        }
        const QByteArray text = filenameStr.toLocal8Bit();
        const gchar *id = text.data();
        const gchar *eventId =id;
        if(desc){
            bool status = false;
            if (QGSettings::isSchemaInstalled(KEY_SOUNDS_SCHEMA)){
                if (m_pSoundSettings->keys().contains("eventSounds")) {
                    status = m_pSoundSettings->get(EVENT_SOUNDS_KEY).toBool();
                }
            }

            if (status && isPlay) {
                retval = ca_context_play (this->caContext, 0,
                                          CA_PROP_EVENT_ID, eventId,
                                          CA_PROP_EVENT_DESCRIPTION, desc, NULL);
            }
            else {
                isPlay = true;
            }
        }
        m_pTimer->stop();
    }
}

void UkmediaMainWidget::setVolumeSettingValue(int value)
{
    if (QGSettings::isSchemaInstalled(UKUI_VOLUME_BRIGHTNESS_GSETTING_ID)) {
        if (m_pVolumeSetting->keys().contains("volumesize")) {
            if(value == 0)
                m_pVolumeControl->setSinkMute(true);
            if (m_pSoundSettings->keys().contains("volumeIncrease")) {
                if(m_pSoundSettings->get("volume-increase").toBool()){
                    int value_increase = (value / 1.25) +0.5;
                    m_pVolumeSetting->blockSignals(true);
                    m_pVolumeSetting->set(UKUI_VOLUME_KEY,value_increase);
                    m_pVolumeSetting->blockSignals(false);
                }
                else {
                    m_pVolumeSetting->blockSignals(true);
                    m_pVolumeSetting->set(UKUI_VOLUME_KEY,value);
                    m_pVolumeSetting->blockSignals(false);
                }
            }
        }
    }
}

void UkmediaMainWidget::setVolumeSettingMute(bool state)
{
    if (QGSettings::isSchemaInstalled(UKUI_VOLUME_BRIGHTNESS_GSETTING_ID)) {
        if (m_pVolumeSetting->keys().contains("soundstate")) {
            m_pVolumeSetting->blockSignals(true);
            m_pVolumeSetting->set(UKUI_VOLUME_STATE,state);
            m_pVolumeSetting->blockSignals(false);
        }
    }
}

void UkmediaMainWidget::themeChangeIcons()
{
    int nInputValue = paVolumeToValue(m_pVolumeControl->getSourceVolume());
    int nOutputValue = paVolumeToValue(m_pVolumeControl->getSinkVolume());
    bool inputStatus = m_pVolumeControl->getSourceMute();
    bool outputStatus = m_pVolumeControl->getSinkMute();

    inputVolumeDarkThemeImage(nInputValue,inputStatus);
    outputVolumeDarkThemeImage(nOutputValue,outputStatus);

    systemWidget->m_pSystemVolumeBtn->repaint();
    appWidget->systemVolumeBtn->repaint();
    soundSystemTrayIcon->setToolTip(tr("Current volume:")+QString::number(nOutputValue)+"%");
}

/*
 * 隐藏窗口
 */
void UkmediaMainWidget::hideWindow()
{
    this->hide();
}

/*
 * 字体改变需更新字体大小
 */
void UkmediaMainWidget::fontSizeChangedSlot(const QString &themeStr)
{
    QString fontType;
    if (m_pFontSetting->keys().contains("systemFont")) {
        fontType = m_pFontSetting->get("systemFont").toString();
    }
    if (m_pFontSetting->keys().contains("systemFontSize")) {
        int font = m_pFontSetting->get("system-font-size").toInt();
        QFont fontSize(fontType,font);
        //listWidget目前使用了qss，需要做特殊处理
        for (int row=0;row<systemWidget->m_pOutputListWidget->count();row++) {
            QListWidgetItem *item = systemWidget->m_pOutputListWidget->item(row);
            UkuiListWidgetItem *wid = (UkuiListWidgetItem *)systemWidget->m_pOutputListWidget->itemWidget(item);
            wid->portLabel->setFont(fontSize);
        }
    }
    Q_EMIT font_change();
}

void UkmediaMainWidget::volumeSettingChangedSlot()
{
    if (m_pVolumeSetting->keys().contains("volumesize")) {
        int valueSetting = m_pVolumeSetting->get(UKUI_VOLUME_KEY).toInt();
        if (valueSetting == 0)
            m_pVolumeControl->setSinkMute(true);
        if (m_pSoundSettings->keys().contains("volumeIncrease")) {
            if(m_pSoundSettings->get("volume-increase").toBool()) {
                int value_increase = (valueSetting * 1.25) +0.5;
                systemWidget->m_pSystemVolumeSlider->setValue(value_increase);
            }
            else
                systemWidget->m_pSystemVolumeSlider->setValue(valueSetting);
        }
    }
    if (QGSettings::isSchemaInstalled(UKUI_VOLUME_BRIGHTNESS_GSETTING_ID)) {
        if (m_pVolumeSetting->keys().contains("soundstate")) {
            bool status = m_pVolumeSetting->get(UKUI_VOLUME_STATE).toBool();

        }
    }
}

/*
 * 系统主题改变
 */
void UkmediaMainWidget::ukuiThemeChangedSlot(const QString &themeStr)
{
    qDebug() << "ukuiThemeChangedSlot" << mThemeName;

    if (m_pThemeSetting->keys().contains("styleName")) {
        mThemeName = m_pThemeSetting->get(UKUI_THEME_NAME).toString();
    }

    themeChangeIcons();
    onTransChanged();
    Q_EMIT qApp->paletteChanged(qApp->palette());
    this->repaint();
}

/*
 * 滑动条控制输出音量
 */
void UkmediaMainWidget::systemVolumeSliderChangedSlot(int value)
{
    QString percent;
    percent = QString::number(value);
    //音量值改变时添加提示音
    int volume = valueToPaVolume(value);
    m_pVolumeControl->getDefaultSinkIndex();
    m_pVolumeControl->setSinkVolume(m_pVolumeControl->sinkIndex,volume);

    appWidget->systemVolumeSlider->blockSignals(true);
    appWidget->systemVolumeDisplayLabel->setText(percent+"%");
    systemWidget->m_pSystemVolumeSliderLabel->setText(percent+"%");
    appWidget->systemVolumeSlider->setValue(value);
    appWidget->systemVolumeSlider->blockSignals(false);

    firstEnterSystem = false;
}

/*
 * 完整模式下，应用音量选项中系统音量控制输出音量值
 */
void UkmediaMainWidget::advancedSystemSliderChangedSlot(int value)
{
    QString percent;
    percent = QString::number(value);
    int volume = valueToPaVolume(value);
    m_pVolumeControl->getDefaultSinkIndex();
    m_pVolumeControl->setSinkVolume(m_pVolumeControl->sinkIndex,volume);
    systemWidget->m_pSystemVolumeSlider->blockSignals(true);
    systemWidget->m_pSystemVolumeSliderLabel->setText(percent+"%");
    appWidget->systemVolumeDisplayLabel->setText(percent+"%");
    systemWidget->m_pSystemVolumeSlider->setValue(value);
    systemWidget->m_pSystemVolumeSlider->blockSignals(false);
}

void UkmediaMainWidget::systemVolumeButtonClickedSlot()
{
    m_pVolumeControl->setSinkMute(!m_pVolumeControl->sinkMuted);

    QTimer * time = new QTimer;
    time->start(100);
    connect(time,&QTimer::timeout,[=](){

        themeChangeIcons();
        time->disconnect();
        delete time;
    });

}

/*
 * 完整模式中应用音量的静音控制
 */
void UkmediaMainWidget::appWidgetMuteButtonCLickedSlot()
{
    m_pVolumeControl->setSinkMute(!m_pVolumeControl->sinkMuted);

    QTimer * time = new QTimer;
    time->start(100);
    connect(time,&QTimer::timeout,[=](){

        themeChangeIcons();
        time->disconnect();
        delete time;
    });
}

/*
 * 声音托盘的触发事件，包括鼠标左键点击，双击，滚轮，右击
 */
void UkmediaMainWidget::activatedSystemTrayIconSlot(QSystemTrayIcon::ActivationReason reason)
{
    QString platform = QGuiApplication::platformName();
    if(!platform.startsWith(QLatin1String("wayland"),Qt::CaseInsensitive)){
        const KWindowInfo info(this->winId(), NET::WMState);
        if (!info.hasState(NET::SkipTaskbar) || !info.hasState(NET::SkipPager)) {
            KWindowSystem::setState(this->winId(), NET::SkipTaskbar | NET::SkipPager);
        }
    }

    switch(reason) {
    //鼠标中间键点击图标
    case QSystemTrayIcon::MiddleClick: {
        if (this->isHidden()) {
            Q_EMIT mouse_middle_clicked_signal();
        }
        else {
            hideWindow();
        }
        break;
    }
        //鼠标左键点击图标
    case QSystemTrayIcon::Trigger: {
        if(this->isVisible()){
            hideWindow();
            break;
        }
        advancedWidgetShow();
        break;
    }
        //鼠标左键双击图标
    case QSystemTrayIcon::DoubleClick: {
        hideWindow();
        break;
    }
    case QSystemTrayIcon::Context:{
        if(this ->isHidden()) {
            menu->popup(QCursor::pos());
        }
        else{
            this->hideWindow();
        }
        break;
    }
    default:
        break;
    }
}

/*
 * 鼠标滚轮点击托盘图标，设置输出音量的静音状态
 */
void UkmediaMainWidget::mouseMeddleClickedTraySlot()
{
    m_pVolumeControl->setSinkMute(!m_pVolumeControl->sinkMuted);

    QTimer * time = new QTimer;
    time->start(100);
    connect(time,&QTimer::timeout,[=](){

        themeChangeIcons();
        time->disconnect();
        delete time;
    });
}

/*
 * 鼠标滚轮在声音托盘上滚动设置输出音量值
 */
void UkmediaMainWidget::trayWheelRollEventSlot(bool step)
{
    int volume = systemWidget->m_pSystemVolumeSlider->value();
    if (step) {
        systemWidget->m_pSystemVolumeSlider->setValue(volume+5);
    }
    else {
        systemWidget->m_pSystemVolumeSlider->setValue(volume-5);
    }
}

/*
 * 点击菜单中声音设置跳转到控制面板的声音控制
 */
void UkmediaMainWidget::jumpControlPanelSlot()
{
    m_process = new QProcess(0);
    m_process->start("ukui-control-center -m Audio");
    m_process->waitForStarted();
    this->hide();
    return;
}

void UkmediaMainWidget::drawImagColorFromTheme(UkuiButtonDrawSvg *button, QString iconStr)
{
    button->themeIcon.image = QIcon::fromTheme(iconStr).pixmap(24,24).toImage();
    button->themeIcon.color = QColor(0,0,0,216);

    if (mThemeName == UKUI_THEME_WHITE) {
        button->themeIcon.color = QColor(255,255,255,216);
    }
    else if (mThemeName == UKUI_THEME_BLACK) {
        button->themeIcon.color = QColor(255,255,255,216);
    }
}

/*
    深色主题时输出音量图标
*/
void UkmediaMainWidget::outputVolumeDarkThemeImage(int value,bool status)
{
    QString iconStr = outputVolumeToIconStr(status,value);

    systemWidget->m_pSystemVolumeBtn->setButtonIcon(QIcon::fromTheme(iconStr));
    appWidget->systemVolumeBtn->setButtonIcon(QIcon::fromTheme(iconStr));
    bool isActive = m_pVolumeControl->getSinkMute();
    if(iconStr == "audio-volume-muted-symbolic" && isActive) {
        systemWidget->m_pSystemVolumeBtn->setActive(false);
        appWidget->systemVolumeBtn->setActive(false);
    }
    else {
        systemWidget->m_pSystemVolumeBtn->setActive(true);
        appWidget->systemVolumeBtn->setActive(true);
    }
    soundSystemTrayIcon->setIcon(QIcon::fromTheme(iconStr));

}

/*
    输入音量图标
*/
void UkmediaMainWidget::inputVolumeDarkThemeImage(int value,bool status)
{
    QString inputIconStr;
    if (status) {
        inputIconStr = iconNameInputs[0];
    }
    else if (value <= 0) {
        inputIconStr = iconNameInputs[0];
    }
    else if (value > 0 && value <= 33) {
        inputIconStr = iconNameInputs[1];
    }
    else if (value >33 && value <= 66) {
        inputIconStr = iconNameInputs[2];
    }
    else {
        inputIconStr = iconNameInputs[3];
    }

    if (mThemeName == "ukui-white" || mThemeName == "ukui-light") {
//        devWidget->inputMuteButton->themeIcon.color = QColor(0,0,0,216);
//        devWidget->inputMuteButton->themeIcon.image = QIcon::fromTheme(inputIconStr).pixmap(24,24).toImage();
    }
    else if (mThemeName == UKUI_THEME_BLACK || mThemeName == "ukui-black" || mThemeName == "ukui-default") {
//        devWidget->inputMuteButton->themeIcon.color = QColor(255,255,255,216);
//        devWidget->inputMuteButton->themeIcon.image = QIcon::fromTheme(inputIconStr).pixmap(24,24).toImage();
    }
}

/*
 * 绘制高亮颜色图标
 */
QPixmap UkmediaMainWidget::drawLightColoredPixmap(const QPixmap &source)
{
    QColor gray(255,255,255);
    QColor standard (0,0,0);
    QImage img = source.toImage();
    for (int x = 0; x < img.width(); x++) {
        for (int y = 0; y < img.height(); y++) {
            auto color = img.pixelColor(x, y);
            if (color.alpha() > 0) {
                if (qAbs(color.red()-gray.red())<20 && qAbs(color.green()-gray.green())<20 && qAbs(color.blue()-gray.blue())<20) {
                    color.setRed(255);
                    color.setGreen(255);
                    color.setBlue(255);
                    img.setPixelColor(x, y, color);
                }
                else {
                    color.setRed(255);
                    color.setGreen(255);
                    color.setBlue(255);
                    img.setPixelColor(x, y, color);
                }
            }
        }
    }
    return QPixmap::fromImage(img);
}

/*
 * 绘制深色颜色图标
 */
QPixmap UkmediaMainWidget::drawDarkColoredPixmap(const QPixmap &source)
{
    QColor gray(255,255,255);
    QImage img = source.toImage();
    for (int x = 0; x < img.width(); x++) {
        for (int y = 0; y < img.height(); y++) {
            auto color = img.pixelColor(x, y);
            if (color.alpha() > 0) {
                if (qAbs(color.red()-gray.red())<20 && qAbs(color.green()-gray.green())<20 && qAbs(color.blue()-gray.blue())<20) {
                    color.setRed(0);
                    color.setGreen(0);
                    color.setBlue(0);
                    img.setPixelColor(x, y, color);
                }
                else {
                    color.setRed(0);
                    color.setGreen(0);
                    color.setBlue(0);
                    img.setPixelColor(x, y, color);
                }
            }
        }
    }
    return QPixmap::fromImage(img);
}

/*
 * 完整模式界面的显示
 */
void UkmediaMainWidget::advancedWidgetShow()
{
    #define MARGIN 4
    QDBusInterface iface("org.ukui.panel",
                         "/panel/position",
                         "org.ukui.panel",
                         QDBusConnection::sessionBus());
    QDBusReply<QVariantList> reply=iface.call("GetPrimaryScreenGeometry");
    QVariantList position_list=reply.value();

    /*
     * 通过这个dbus接口获取到的6个参数分别为 ：可用屏幕大小的x坐标、y坐标、宽度、高度，任务栏位置
    */
     QRect rect;
    switch(reply.value().at(4).toInt()){
    case 1:
        rect = QRect(position_list.at(0).toInt()+position_list.at(2).toInt()-this->width()-MARGIN,
                    position_list.at(1).toInt()+MARGIN,
                    this->width(),this->height());
        break;
    case 2:
        rect = QRect(position_list.at(0).toInt()+MARGIN,
                     position_list.at(1).toInt()+reply.value().at(3).toInt()-this->height()-MARGIN,
                     this->width(),this->height());
        break;
    case 3:
        rect = QRect(position_list.at(0).toInt()+position_list.at(2).toInt()-this->width()-MARGIN,
                     position_list.at(1).toInt()+reply.value().at(3).toInt()-this->height()-MARGIN,
                     this->width(),this->height());
        break;
    default:
        rect = QRect(position_list.at(0).toInt()+position_list.at(2).toInt()-this->width()-MARGIN,
                     position_list.at(1).toInt()+reply.value().at(3).toInt()-this->height()-MARGIN,
                     this->width(),this->height());
        break;
    }

    QString platform = QGuiApplication::platformName();
    if(!platform.startsWith(QLatin1String("wayland"),Qt::CaseInsensitive)){
        this->setGeometry(rect);
        this->showNormal();
    }
    else {
        kdk::UkuiStyleHelper::self()->removeHeader(this);
        this->show();
        kdk::WindowManager::setGeometry(this->windowHandle(), rect);
    }
    this->raise();
    this->activateWindow();
}

QString UkmediaMainWidget::appNameToIconName(const gchar *appName,const gchar *appIconName)
{
    QString iconName = "/usr/share/applications/";
    qDebug()<< "appNameToIconName" << appName << appIconName;
    /*!
     * \brief
     * \details
     * 由于获取到的麒麟影音软件获取的app icon不正确
     * 可能是软件没有发出正确的信号告知正确的icon，
     * 因此添加判断当匹配应用名为Kylinvideo时设置
     * 正确的icon名来保证找到正确的desktop,从而设置
     * 应用音量正确的应用名和图标
     */
    if (strcmp(appName,"KylinVideo") == 0) {
        appIconName = "kylin-video";
    }

    if (strcmp(appName,"wine-preloader") == 0)
    {
        QString weChatStr = findFile(iconName,"微信");
        if (weChatStr == "")
            weChatStr = "kylin-kwre-wechat.desktop";
        iconName.append(weChatStr);//wine版
    }
    else{
        iconName.append(appIconName);
        iconName.append(".desktop");
    }


    return iconName;
}

void UkmediaMainWidget::addAppToAppwidget(const gchar *appName,const gchar *appIconName,int index,int value,int channel)
{
    //设置应用的图标
    QString iconName = appNameToIconName(appName,appIconName);
    QString description = appName;
    QString pAppName = getAppName(iconName);
    QString pAppIcon = getAppIcon(iconName);
    initSubApplicationWidget(pAppIcon);
    qDebug() << "add application to widget" << appName<< appIconName << pAppIcon << iconName;

    appWidget->app_volume_list->append(appIconName);
    QString appSliderStr = appName;
    QString appMuteBtnlStr = appName;
    QString appVolumeLabelStr = appName;

    QStringList strList;
    strList<<appMuteBtnlStr<<appSliderStr;
    appWidget->appSlider->setObjectName(appSliderStr);
    appWidget->appMuteBtn->setObjectName(appIconName);
    appWidget->appVolumeLabel->setObjectName(appVolumeLabelStr);

    //初始化应用音量滑动条
    int sliderValue = paVolumeToValue(value);
    appWidget->appIconBtn->setCheckable(false);
    appWidget->appIconBtn->setChecked(false);
    appWidget->appSlider->blockSignals(true);
    appWidget->appSlider->setValue(sliderValue);
    appWidget->appVolumeLabel->setText(QString::number(sliderValue)+"%");
    appWidget->appSlider->blockSignals(false);
    qDebug() << "初始化应用音量滑动条:" << appWidget->appSlider->value() << appSliderStr;

    /*滑动条控制应用音量*/
    connect(appWidget->appSlider,&QSlider::valueChanged,[=](int value)
    {
        bool isMute = false;
        int volume = valueToPaVolume(value);
        QString appName = appSliderStr.split("Slider").at(0);

        qDebug() << "调节应用音量滑动条的index和appName" << index << appName;

        //因为一个应用可能产生多个sinkinput，所以要对相同description的所有index设置音量，遍历indexmap设置
        QMap<int, QString>::iterator it;
        for(it = m_pVolumeControl->sinkInputIndexMap.begin(); it != m_pVolumeControl->sinkInputIndexMap.end();){
            if(it.value() == appName){
                m_pVolumeControl->setSinkInputVolume(it.key(),volume,channel);
            }
            it++;
        }
        for(it = m_pVolumeControl->sourceOutputIndexMap.begin(); it != m_pVolumeControl->sourceOutputIndexMap.end();){
            if(it.value() == appName){
                m_pVolumeControl->setSourceOutputVolume(it.key(),volume,channel);
            }
            it++;
        }

        if(kylinVideoVolumeSignal)
            kylinVideoVolumeSignal = false;
        else {
            QDBusMessage message =QDBusMessage::createSignal("/", "org.ukui.media", "sinkVolumeChanged");
            message<<pAppIcon<<value<<false;
            QDBusConnection::sessionBus().send(message);
        }

        QLabel *label = appWidget->findChild<QLabel*> (appVolumeLabelStr);
        if (label == nullptr)
            return;
        label->setText(QString::number(value)+"%");

        QSlider *slider = appWidget->findChild<QSlider*>(appSliderStr);
        if (slider == nullptr)
            return;
        QPushButton *btn = appWidget->findChild<QPushButton*>(appMuteBtnlStr);
        if (btn == nullptr)
            return;
        QString audioIconStr = outputVolumeToIconStr(isMute,value);
        QSize iconSize(24,24);
        if ( mThemeName == "ukui-white" || mThemeName == "ukui-light") {
            btn->setIcon(QIcon(drawDarkColoredPixmap((QIcon::fromTheme(audioIconStr).pixmap(iconSize)))));
        }
        else if (mThemeName == UKUI_THEME_BLACK || mThemeName == "ukui-black" || mThemeName == "ukui-default") {
            btn->setIcon(QIcon(drawLightColoredPixmap((QIcon::fromTheme(audioIconStr).pixmap(iconSize)))));
        }
        Q_EMIT app_name_signal(appSliderStr);
    });

    connect(appWidget->appMuteBtn,&QPushButton::clicked,[=]()
    {
        bool isMute = false;
        int volume = -1;

        isMute = m_pVolumeControl->getSinkInputMuted(description);
        qDebug() << "appMuteBtn clicked" << "muted" << isMute << description <<isAppMuteBtnPress;

        volume = int(volume*100/65536.0 + 0.5);
        if (sinkInputMute != isMute) {
            m_pVolumeControl->setSinkInputMuted(index,!isMute);
            if (isAppMuteBtnPress) {
                isAppMuteBtnPress = false;
            }
        }
        else {
            if(kylinVideoMuteSignal)
                kylinVideoMuteSignal = false;
            else{
                QDBusMessage message =QDBusMessage::createSignal("/", "org.ukui.media", "sinkVolumeChanged");
                message<<pAppIcon<<volume<<!isMute;
                QDBusConnection::sessionBus().send(message);
            }
        }
    });
}

void UkmediaMainWidget::sinkInputVolumeChangedSlot(const gchar *appName, const gchar *appIconName, int value)
{
    QString appSliderStr = appName;
    appSliderStr.append("Slider");
    QString appLabelStr = appName;
    appLabelStr.append("VolumeLabel");

    QLabel *label = appWidget->displayAppVolumeWidget->findChild<QLabel *>(appName);
    QSlider *s = appWidget->displayAppVolumeWidget->findChild<QSlider *>(appName);

    if (s == nullptr || appIconName == nullptr)
        return;

    s->blockSignals(true);
    label->setText(QString::number(paVolumeToValue(value))+"%");
    s->setValue(paVolumeToValue(value));
    s->blockSignals(false);

    qDebug() << "sinkInputVolumeChangedSlot" << appName << appIconName << value << appSliderStr;
}

void UkmediaMainWidget::soundSettingChanged(const QString &key)
{
    qDebug() << "soundSettingChanged" << key;
    if (key == "dnsNoiseReduction")
        switchModuleEchoCancel();
    else if (key == "volumeIncrease")
        resetVolumeSliderRange();
}

/*
 * 获取应用名称，从desktop全路径名下解析出应用名称
 */
QString UkmediaMainWidget::getAppName(QString desktopfp)
{
    GError** error=nullptr;
    GKeyFileFlags flags=G_KEY_FILE_NONE;
    GKeyFile* keyfile=g_key_file_new ();

    QByteArray fpbyte=desktopfp.toLocal8Bit();
    char* filepath=fpbyte.data();
    g_key_file_load_from_file(keyfile,filepath,flags,error);

    char* name=g_key_file_get_locale_string(keyfile,"Desktop Entry","Name", nullptr, nullptr);
    QString namestr=QString::fromLocal8Bit(name);

    g_key_file_free(keyfile);
    return namestr;
}

/*
 * 获取应用图标，从desktop全路径名下解析出应用图标
 */
QString UkmediaMainWidget::getAppIcon(QString desktopfp)
{
    GError** error=nullptr;
    GKeyFileFlags flags=G_KEY_FILE_NONE;
    GKeyFile* keyfile=g_key_file_new ();

    QByteArray fpbyte=desktopfp.toLocal8Bit();
    char* filepath=fpbyte.data();
    g_key_file_load_from_file(keyfile,filepath,flags,error);

    char* name=g_key_file_get_locale_string(keyfile,"Desktop Entry","Icon", nullptr, nullptr);
    QString namestr=QString::fromLocal8Bit(name);

    g_key_file_free(keyfile);
    return namestr;
}

void UkmediaMainWidget::initSubApplicationWidget(QString pAppIcon)
{
    //widget显示应用音量
    QWidget *subAppwidget = new QWidget(appWidget->displayAppVolumeWidget);
    appWidget->appVolumeLabel = new QLabel(subAppwidget);
    appWidget->appVolumeLabel->setParent(subAppwidget);
    appWidget->appIconBtn = new QPushButton(subAppwidget);
    appWidget->appMuteBtn = new QPushButton(subAppwidget);
    appWidget->appMuteBtn->setVisible(false);
    appWidget->appSlider = new UkmediaVolumeSlider(subAppwidget);
    appWidget->appSlider->setOrientation(Qt::Horizontal);
    appWidget->appIconBtn->setFixedSize(36,36);
    appWidget->appIconBtn->setFlat(true);
    appWidget->appIconBtn->setFocusPolicy(Qt::NoFocus);
    QSize icon_size(32,32);
    appWidget->appIconBtn->setIconSize(icon_size);
    appWidget->appIconBtn->setIcon(QIcon::fromTheme(pAppIcon));
    appWidget->appIconBtn->setAttribute(Qt::WA_TranslucentBackground);

    QPalette palete = appWidget->appIconBtn->palette();
    palete.setColor(QPalette::Highlight,Qt::transparent);
    palete.setBrush(QPalette::Button,QBrush(QColor(1,1,1,0)));
    appWidget->appIconBtn->setPalette(palete);

    QPalette paleteAppIcon =  appWidget->appIconBtn->palette();
    paleteAppIcon.setColor(QPalette::Highlight,Qt::transparent);
    paleteAppIcon.setBrush(QPalette::Button,QBrush(QColor(0,0,0,0)));
    appWidget->appIconBtn->setPalette(paleteAppIcon);

    appWidget->appSlider->setMaximum(100);
    appWidget->appSlider->setFixedSize(273,48);
    appWidget->appIconBtn->adjustSize();
    appWidget->appIconBtn->setProperty("useIconHighlightEffect",true);
    appWidget->appIconBtn->setProperty("iconHighlightEffectMode",true);
    appWidget->appIconBtn->setStyleSheet("QPushButton{background:transparent;border:0px;"
                                                "padding-left:0px;}"
                                                "QPushButton:hover {"
                                                "background-color: #00000000;"
                                                "color: white;}");


    //音量滑动条
    QHBoxLayout *appSliderLayout = new QHBoxLayout();

    subAppwidget->setFixedSize(412,48);
    appWidget->appVolumeLabel->setFixedSize(55,48);
    appWidget->appVolumeLabel->setAlignment(Qt::AlignCenter);
    appSliderLayout->addWidget(appWidget->appIconBtn);
    appSliderLayout->addSpacing(8);
    appSliderLayout->addWidget(appWidget->appSlider);
//    appSliderLayout->addItem(new QSpacerItem(16,20,QSizePolicy::Maximum));
    appSliderLayout->addWidget(appWidget->appVolumeLabel);
    appSliderLayout->setSpacing(0);
    subAppwidget->setLayout(appSliderLayout);
    appSliderLayout->setContentsMargins(16,0,24,0);
    appWidget->m_pVlayout->addWidget(subAppwidget);
//    //设置布局的垂直间距以及设置vlayout四周的间距
    appWidget->displayAppVolumeWidget->resize(404,m_pVolumeControl->sinkInputList.count()*50);
    appWidget->m_pVlayout->setSpacing(2);
    appWidget->m_pVlayout->setContentsMargins(0,0,0,0);
    appWidget->m_pVlayout->update();

}

/*
 * 当播放或录制应用退出时删除在应用音量界面上该应用的显示
 */
void UkmediaMainWidget::removeSubAppWidget(const gchar *m_pAppName)
{
    g_debug ("Removing application stream %s", m_pAppName);
    /* We could call bar_set_stream_control here, but that would pointlessly
         * invalidate the channel bar, so just remove it ourselves */
    int index = -1;
    for (int i=0;i<m_pVolumeControl->sinkInputList.count();i++) {
        if (m_pVolumeControl->sinkInputList.at(i) == m_pAppName) {
            index = i;
            m_pVolumeControl->sinkInputList.removeAt(i);
            break;
        }
    }
    if (index == -1)
        return;
    QLayoutItem *item;
    if ((item = appWidget->m_pVlayout->takeAt(index)) != 0) {
        QWidget *wid = item->widget();
        appWidget->m_pVlayout->removeWidget(wid);
        wid->setParent(nullptr);
        delete wid;
        delete item;
    }
    qDebug() << "removeSubAppWidget" << m_pAppName << m_pVolumeControl->sinkInputList.count();
    //设置布局的间距以及设置vlayout四周的间距
    appWidget->displayAppVolumeWidget->resize(404,m_pVolumeControl->sinkInputList.count()*50);
    appWidget->m_pVlayout->setSpacing(2);
    appWidget->m_pVlayout->setContentsMargins(0,0,0,0);
    appWidget->m_pVlayout->update();

}

/*
   In PulseAudio without ucm, ports will show up with the following names:
   Headphones - analog-output-headphones
   Headset mic - analog-input-headset-mic (was: analog-input-microphone-headset)
   Jack in mic-in mode - analog-input-headphone-mic (was: analog-input-microphone)

   However, since regular mics also show up as analog-input-microphone,
   we need to check for certain controls on alsa mixer level too, to know
   if we deal with a separate mic jack, or a multi-function jack with a
   mic-in mode (also called "headphone mic").
   We check for the following names:

   Headphone Mic Jack - indicates headphone and mic-in mode share the same jack,
     i e, not two separate jacks. Hardware cannot distinguish between a
     headphone and a mic.
   Headset Mic Phantom Jack - indicates headset jack where hardware can not
     distinguish between headphones and headsets
   Headset Mic Jack - indicates headset jack where hardware can distinguish
     between headphones and headsets. There is no use popping up a dialog in
     this case, unless we already need to do this for the mic-in mode.

   From the PA_PROCOTOL_VERSION=34, The device_port structure adds 2 members
   availability_group and type, with the help of these 2 members, we could
   consolidate the port checking and port setting for non-ucm and with-ucm
   cases.
*/

#define HEADSET_PORT_SET(dst, src) \
        do { \
                if (!(dst) || (dst)->priority < (src)->priority) \
                        dst = src; \
        } while (0)

#define GET_PORT_NAME(x) (x ? g_strdup (x->name) : NULL)

headsetPorts *
UkmediaMainWidget::getHeadsetPorts (const pa_card_info *c)
{
    headsetPorts *h;
    guint i;

    h = g_new0 (headsetPorts, 1);

    for (i = 0; i < c->n_ports; i++) {
        pa_card_port_info *p = c->ports[i];
        //                if (control->priv->server_protocol_version < 34) {
        if (g_str_equal (p->name, "analog-output-headphones") || g_str_equal (p->name, "[Out] Headphones1"))
            h->headphones = p;
        else if (g_str_equal (p->name, "analog-input-headset-mic") || g_str_equal (p->name, "[In] Headset"))
            h->headsetmic = p;
        else if (g_str_equal (p->name, "analog-input-headphone-mic") || g_str_equal (p->name, "[In] Headphones2"))
            h->headphonemic = p;
        else if (g_str_equal (p->name, "analog-input-internal-mic") || g_str_equal (p->name, "[In] Mic"))
            h->internalmic = p;
        else if (g_str_equal (p->name, "analog-output-speaker") || g_str_equal (p->name, "[Out] Speaker"))
            h->internalspk = p;
        //                } else {
#if (PA_PROTOCOL_VERSION >= 34)
        /* in the first loop, set only headphones */
        /* the microphone ports are assigned in the second loop */
        if (p->type == PA_DEVICE_PORT_TYPE_HEADPHONES) {
            if (p->availability_group)
                HEADSET_PORT_SET (h->headphones, p);
        } else if (p->type == PA_DEVICE_PORT_TYPE_SPEAKER) {
            HEADSET_PORT_SET (h->internalspk, p);
        } else if (p->type == PA_DEVICE_PORT_TYPE_MIC) {
            if (!p->availability_group)
                HEADSET_PORT_SET (h->internalmic, p);
        }
#else
        //                        g_warning_once ("libgnome-volume-control running against PulseAudio %u, "
        //                                        "but compiled against older %d, report a bug to your distribution",
        //                                        control->priv->server_protocol_version,
        //                                        PA_PROTOCOL_VERSION);
#endif
        //                }
    }

    return h;
}

gboolean
UkmediaMainWidget::verifyAlsaCard (int cardindex,
                                      gboolean *headsetmic,
                                      gboolean *headphonemic)
{
    char *ctlstr;
    snd_hctl_t *hctl;
    snd_ctl_elem_id_t *id;
    int err;

    *headsetmic = FALSE;
    *headphonemic = FALSE;

    ctlstr = g_strdup_printf ("hw:%i", cardindex);
    if ((err = snd_hctl_open (&hctl, ctlstr, 0)) < 0) {
        g_warning ("snd_hctl_open failed: %s", snd_strerror(err));
        g_free (ctlstr);
        return FALSE;
    }
    g_free (ctlstr);

    if ((err = snd_hctl_load (hctl)) < 0) {
//        if (hasNo && !hasOther)
        g_warning ("snd_hctl_load failed: %s", snd_strerror(err));
        snd_hctl_close (hctl);
        return FALSE;
    }

    snd_ctl_elem_id_alloca (&id);

    snd_ctl_elem_id_clear (id);
    snd_ctl_elem_id_set_interface (id, SND_CTL_ELEM_IFACE_CARD);
    snd_ctl_elem_id_set_name (id, "Headphone Mic Jack");
    if (snd_hctl_find_elem (hctl, id))
        *headphonemic = TRUE;

    snd_ctl_elem_id_clear (id);
    snd_ctl_elem_id_set_interface (id, SND_CTL_ELEM_IFACE_CARD);
    snd_ctl_elem_id_set_name (id, "Headset Mic Phantom Jack");
    if (snd_hctl_find_elem (hctl, id))
        *headsetmic = TRUE;

    if (*headphonemic) {
        snd_ctl_elem_id_clear (id);
        snd_ctl_elem_id_set_interface (id, SND_CTL_ELEM_IFACE_CARD);
        snd_ctl_elem_id_set_name (id, "Headset Mic Jack");
        if (snd_hctl_find_elem (hctl, id))
            *headsetmic = TRUE;
    }

    snd_hctl_close (hctl);
    return *headsetmic || *headphonemic;
}

void UkmediaMainWidget::checkAudioDeviceSelectionNeeded (const pa_card_info *info)
{
    headsetPorts *h;
    gboolean start_dialog, stop_dialog;
    qDebug() << "check_audio_device_selection_needed" <<info->name;

    start_dialog = FALSE;
    stop_dialog = FALSE;
    h = getHeadsetPorts (info);

    if (!h->headphones || (!h->headsetmic && !h->headphonemic)) {
        qDebug() << "no headset jack" ;
        isPlay = false;
        /* Not a headset jack */
        goto out;
    }
    else {
        qDebug() << "headset jack" << h->headphonemic << h->headphones;
    }
    if (headsetCard != (int) info->index) {
        int cardindex;
        gboolean hsmic = TRUE;
        gboolean hpmic = TRUE;
        const char *s;

        s = pa_proplist_gets (info->proplist, "alsa.card");
        if (!s)
            goto out;

        cardindex = strtol (s, NULL, 10);
        if (cardindex == 0 && strcmp(s, "0") != 0)
            goto out;
        if (!verifyAlsaCard(cardindex, &hsmic, &hpmic))
            goto out;

        headsetCard = info->index;
        hasHeadsetmic = hsmic && h->headsetmic;
        hasHeadphonemic = hpmic && h->headphonemic;
    } else {
        start_dialog = (h->headphones->available != PA_PORT_AVAILABLE_NO) && !headsetPluggedIn;
        stop_dialog = (h->headphones->available == PA_PORT_AVAILABLE_NO) && headsetPluggedIn;
    }

    headsetPluggedIn = h->headphones->available != PA_PORT_AVAILABLE_NO;
    m_pHeadphonesName = GET_PORT_NAME(h->headphones);
    m_pHeadsetmicName = GET_PORT_NAME(h->headsetmic);
    m_pHeadphonemicName = GET_PORT_NAME(h->headphonemic);
    m_pInternalspkName = GET_PORT_NAME(h->internalspk);
    m_pInternalmicName = GET_PORT_NAME(h->internalmic);

    if (firstLoad)
        firstLoad = false;
    else {
        if (headsetPluggedIn) {
            headsetWidget->showWindow();
        }
        else {
            if (headsetWidget->isShow) {
                headsetWidget->hide();
                headsetWidget->isShow = false;
            }
        }
    }
    qDebug() << "check_audio_device_selection_needed" <<m_pHeadphonesName <<m_pHeadsetmicName << m_pHeadphonemicName <<m_pInternalspkName << m_pInternalmicName << headsetPluggedIn;
    if (!start_dialog &&
            !stop_dialog)
        goto out;
out:
    g_free (h);
}

void UkmediaMainWidget::freePrivPortNames ()
{
    g_clear_pointer (&m_pHeadphonesName, g_free);
    g_clear_pointer (&m_pHeadsetmicName, g_free);
    g_clear_pointer (&m_pHeadphonemicName, g_free);
    g_clear_pointer (&m_pInternalspkName, g_free);
    g_clear_pointer (&m_pInternalmicName, g_free);
}


void UkmediaMainWidget::onPrepareForSleep(bool sleep)
{
    ///系统休眠时，sink未进入suspend状态
    ///在系统休眠之前将默认的sink设置成suspend状态，在系统唤醒后在将默认的sink设置成running状态

    qDebug() << "ctf ----- onPrepareForSleep"  << sleep << m_pVolumeControl->defaultSinkName;
    if(sleep)
    {
        system("pacmd suspend 1");
//        pa_context_suspend_sink_by_name(m_pVolumeControl->getContext(),m_pVolumeControl->defaultSinkName,1,nullptr,nullptr);
        uninhibit();
    }
    else
    {
        system("pacmd suspend 0");
//        pa_context_suspend_sink_by_name(m_pVolumeControl->getContext(),m_pVolumeControl->defaultSinkName,0,nullptr,nullptr);
        inhibit();
    }
}

/*
    输出设备提示弹窗
*/
void UkmediaMainWidget::deviceChangedShowSlot(QString dev_name)
{
    #define MARGIN 4
    QDBusInterface iface("org.ukui.panel",
                         "/panel/position",
                         "org.ukui.panel",
                         QDBusConnection::sessionBus());
    QDBusReply<QVariantList> reply=iface.call("GetPrimaryScreenGeometry");
    QVariantList position_list=reply.value();



    QPixmap dev_Icon;

    if ( mThemeName == "ukui-white" || mThemeName == "ukui-light") {
        dev_Icon = drawDarkColoredPixmap((QIcon::fromTheme(dev_name)).pixmap(48,48));
    }
    else if (mThemeName == UKUI_THEME_BLACK || mThemeName == "ukui-black" || mThemeName == "ukui-default") {
        dev_Icon = drawLightColoredPixmap((QIcon::fromTheme(dev_name)).pixmap(48,48));
    }

    //获取透明度
//    if (QGSettings::isSchemaInstalled(UKUI_THEME_SETTING)){
//        if (m_pTransparencySetting->keys().contains("transparency")) {
//            transparency = m_pTransparencySetting->get("transparency").toDouble();
//        }
//    }

    if (!osdWidget->isHidden()) {
        osdWidget->hide();

        if (timer != nullptr) {
            timer->disconnect();
            timer = nullptr;
            delete timer;
        }
    }

    osdWidget->UkmediaOsdSetIcon(dev_Icon,mThemeName);

    kdk::UkuiStyleHelper::self()->removeHeader(osdWidget);

    osdWidget->show();

    QRect rect = QRect(position_list.at(0).toInt()+position_list.at(2).toInt()-osdWidget->width()-200,
                       position_list.at(1).toInt()+reply.value().at(3).toInt()-osdWidget->height()-MARGIN,
                       osdWidget->width(),osdWidget->height());

    kdk::WindowManager::setGeometry(osdWidget->windowHandle(),rect);

//    osdWidget->setWindowOpacity(transparency);
    timer = new MyTimer(osdWidget); //this 为parent类, 表示当前窗口
    connect(timer, SIGNAL(timeOut()), this, SLOT(osdDisplayWidgetHide()));

}

//osd超时隐藏
void UkmediaMainWidget::osdDisplayWidgetHide()
{
    this->osdWidget->hide();
}

/*
 * 更新设备端口
 */
void UkmediaMainWidget::updateDevicePort()
{
    QMap<int,QMap<QString,QString>>::iterator it;
    QMap<QString,QString>::iterator at;
    QMap<QString,QString> temp;
    currentInputPortLabelMap.clear();
    currentOutputPortLabelMap.clear();
    if (firstEntry == true) {
        for(it = m_pVolumeControl->outputPortMap.begin();it!=m_pVolumeControl->outputPortMap.end();)
        {
            temp = it.value();
            for (at=temp.begin();at!=temp.end();) {
                qDebug() << "updateDevicePort" << firstEntry << it.key() << at.value() <<at.key();
                QString cardName = findCardName(it.key(),m_pVolumeControl->cardMap);
                addOutputListWidgetItem(at.key(),at.value(),cardName);
                ++at;
            }
            ++it;
        }
        for(it = m_pVolumeControl->inputPortMap.begin();it!=m_pVolumeControl->inputPortMap.end();)
        {
            temp = it.value();
            for (at=temp.begin();at!=temp.end();) {
                qDebug() << "updateDevicePort" << firstEntry << it.key() << at.value();
                QString cardName = findCardName(it.key(),m_pVolumeControl->cardMap);
                addInputListWidgetItem(at.value(),cardName);
                ++at;
            }
            ++it;
        }

    }
    else {

        //记录上一次output label
        for (int i=0;i<systemWidget->m_pOutputListWidget->count();i++) {
            QMap<int,QString>::iterator at;
            QListWidgetItem *item = systemWidget->m_pOutputListWidget->item(i);
            UkuiListWidgetItem *wid = (UkuiListWidgetItem *)systemWidget->m_pOutputListWidget->itemWidget(item);
            int index;
            for (at=m_pVolumeControl->cardMap.begin();at!=m_pVolumeControl->cardMap.end();) {
                if (wid->deviceLabel->text() == at.value()) {
                    index = at.key();
                    break;
                }
                ++at;
            }
            currentOutputPortLabelMap.insertMulti(index,wid->portLabel->fullText);
//            qDebug() << index << "current output item ************" << wid->deviceLabel->text() <<wid->portLabel->text() ;//<< w->m_pOutputPortLabelList->at(i);
        }

        for (int i=0;i<systemWidget->m_pInputListWidget->count();i++) {

            QListWidgetItem *item = systemWidget->m_pInputListWidget->item(i);
            UkuiListWidgetItem *wid = (UkuiListWidgetItem *)systemWidget->m_pInputListWidget->itemWidget(item);
            int index;
            int count;
            QMap<int,QString>::iterator at;
            for (at=m_pVolumeControl->cardMap.begin();at!=m_pVolumeControl->cardMap.end();) {
                if (wid->deviceLabel->text() == at.value()) {
                    index = at.key();
                    break;
                }
                ++at;
                ++count;
            }
            currentInputPortLabelMap.insertMulti(index,wid->portLabel->fullText);
        }
        systemWidget->m_pInputListWidget->blockSignals(true);
        deleteNotAvailableOutputPort();
        addAvailableOutputPort();
        deleteNotAvailableInputPort();
        addAvailableInputPort();
        systemWidget->m_pInputListWidget->blockSignals(false);
    }
    if (systemWidget->m_pOutputListWidget->count() > 0 /*|| m_pInputWidget->m_pInputListWidget->count()*/) {

        firstEntry = false;
    }
}

void UkmediaMainWidget::updateListWidgetItemSlot()
{
    qDebug() << "updateListWidgetItemSlot---------";

    initOutputListWidgetItem();
    initInputListWidgetItem();
    themeChangeIcons();
    switchModuleEchoCancel();
}

/*
 * output list widget选项改变，设置对应的输出设备
 */
void UkmediaMainWidget::outputListWidgetCurrentRowChangedSlot(int row)
{
    //当所有可用的输出设备全部移除，台式机才会出现该情况
    if (row == -1)
        return;
    QListWidgetItem *item = systemWidget->m_pOutputListWidget->item(row);
    if (item == nullptr) {
        qDebug() <<"output current item is null";
    }
    UkuiListWidgetItem *wid = (UkuiListWidgetItem *)systemWidget->m_pOutputListWidget->itemWidget(item);
    QListWidgetItem *inputCurrrentItem = systemWidget->m_pInputListWidget->currentItem();
    UkuiListWidgetItem *inputWid = (UkuiListWidgetItem *)systemWidget->m_pInputListWidget->itemWidget(inputCurrrentItem);
    bool isContainBlue = inputDeviceContainBluetooth();

    wid->deviceButton->buttonState = PUSH_BUTTON_CLICK;
    wid->deviceButton->setActive(true);
    setDeviceButtonState(row);

    //当输出设备从蓝牙切换到其他设备时，需将蓝牙声卡的配置文件切换为a2dp-sink
    if (isContainBlue && (strstr(m_pVolumeControl->defaultSourceName,"headset_head_unit") || strstr(m_pVolumeControl->defaultSourceName,"bt_sco_sink"))) {
        QString cardName = blueCardName();
        setCardProfile(cardName,"a2dp_sink");
    }
    QStringList comboboxPortNameList = wid->portLabel->text().split("（");
    QStringList inputComboboxPortNameList;
    if(inputWid)
        inputComboboxPortNameList = inputWid->portLabel->text().split("（");


    QMap<int,QMap<QString,QString>>::iterator outputProfileMap;
    QMap<int,QMap<QString,QString>>::iterator inputProfileMap;
    QMap<QString,QString> tempMap;
    QMap<QString,QString>::iterator at;
    QString endOutputProfile = "";
    QString endInputProfile = "";

    int currentCardIndex = findCardIndex(wid->deviceLabel->text(),m_pVolumeControl->cardMap);
    int count,i;

    for (outputProfileMap=m_pVolumeControl->profileNameMap.begin();outputProfileMap!= m_pVolumeControl->profileNameMap.end();) {
        if(currentCardIndex == outputProfileMap.key()){
            tempMap = outputProfileMap.value();
            for(at=tempMap.begin(),i=0;at!= tempMap.end();++i){
                if (at.key() == comboboxPortNameList.at(0)) {
                    count = i;
                    endOutputProfile = at.value();
                }
                ++at;
            }
        }
        ++outputProfileMap;
    }

    if (inputCurrrentItem != nullptr) {
        QMap <QString,QString>::iterator it;
        QMap <QString,QString> temp;
        int index = findCardIndex(inputWid->deviceLabel->text(),m_pVolumeControl->cardMap);
        for (inputProfileMap=m_pVolumeControl->inputPortProfileNameMap.begin(),count=0;inputProfileMap!= m_pVolumeControl->inputPortProfileNameMap.end();count++) {
            if (inputProfileMap.key() == index) {
                temp = inputProfileMap.value();
                for(it=temp.begin();it!=temp.end();){
                    if(it.key() == inputComboboxPortNameList.at(0)){
                        endInputProfile = it.value();
                    }
                    ++it;
                }
            }
            ++inputProfileMap;
        }
    }
    qDebug() << "outputListWidgetCurrentRowChangedSlot" << row << wid->deviceLabel->text() << endOutputProfile <<endInputProfile;
    //如果选择的输入输出设备为同一个声卡，则追加指定输入输出端口属于的配置文件
    if ((inputCurrrentItem != nullptr && wid->deviceLabel->text() == inputWid->deviceLabel->text()) || \
            wid->deviceLabel->text() == "alsa_card.platform-sound_DA_combine_v5" && inputWid->deviceLabel->text() == "3a.algo") {

        QString setProfile = endOutputProfile;
        if (!endOutputProfile.contains("input:analog-stereo") || !endOutputProfile.contains("HiFi")) {
            setProfile += "+";
            setProfile +=endInputProfile;
        }

        setCardProfile(wid->deviceLabel->text(),setProfile);
        setDefaultOutputPortDevice(wid->deviceLabel->text(),wid->portLabel->fullText);
    }
    //如果选择的输入输出设备不是同一块声卡，需要设置一个优先级高的配置文件
    else {
        int index = findCardIndex(wid->deviceLabel->text(),m_pVolumeControl->cardMap);
        QMap <int,QList<QString>>::iterator it;
        QString profileName;
        for(it=m_pVolumeControl->cardProfileMap.begin();it!=m_pVolumeControl->cardProfileMap.end();) {
            if (it.key() == index) {
                if (strstr(endOutputProfile.toLatin1().data(),"headset_head_unit"))
                    endOutputProfile = "a2dp_sink";
                profileName = findHighPriorityProfile(index,endOutputProfile);
            }
            ++it;
        }

        QString setProfile = profileName;
        setCardProfile(wid->deviceLabel->text(),setProfile);
        setDefaultOutputPortDevice(wid->deviceLabel->text(),wid->portLabel->fullText);
    }
    qDebug() << "active output port:" << wid->portLabel->fullText << wid->deviceLabel->text();
}

/*
 * input list widget选项改变，设置对应的输入设备
 */
void UkmediaMainWidget::inputListWidgetCurrentRowChangedSlot(int row)
{
    //当所有可用的输入设备全部移除，台式机才会出现该情况
    if (row == -1)
        return;
    QListWidgetItem *item = systemWidget->m_pInputListWidget->item(row);
    UkuiListWidgetItem *wid = (UkuiListWidgetItem *)systemWidget->m_pInputListWidget->itemWidget(item);
    QListWidgetItem *outputCurrrentItem = systemWidget->m_pOutputListWidget->currentItem();
    UkuiListWidgetItem *outputWid = (UkuiListWidgetItem *)systemWidget->m_pOutputListWidget->itemWidget(outputCurrrentItem);

    bool isContainBlue = inputDeviceContainBluetooth();
    qDebug() << "inputListWidgetCurrentRowChangedSlot" << row << isContainBlue << m_pVolumeControl->defaultSourceName;
    //当输出设备从蓝牙切换到其他设备时，需将蓝牙声卡的配置文件切换为a2dp-sink
    if (isContainBlue && (strstr(m_pVolumeControl->defaultSinkName,"headset_head_unit") || strstr(m_pVolumeControl->defaultSourceName,"bt_sco_source"))) {
        QString cardName = blueCardName();
        setCardProfile(cardName,"a2dp_sink");
    }

    if(wid->deviceLabel->text().contains("bluez_card")) {
        isCheckBluetoothInput = true;
    }
    else {
        isCheckBluetoothInput = false;
    }

    QMap<int, QMap<QString,QString>>::iterator inputProfileMap;
    QMap<int, QMap<QString,QString>>::iterator outputProfileMap;
    QMap <QString,QString> temp;
    QMap<QString,QString>::iterator at;
    QString endOutputProfile = "";
    QString endInputProfile = "";
    int index = findCardIndex(wid->deviceLabel->text(),m_pVolumeControl->cardMap);

    QStringList inputcomboboxPortNameList = wid->portLabel->text().split("（");//新增设计combobox需要显示 端口名+(description)
    QStringList comboboxPortNameList = outputWid->portLabel->text().split("（");//新增设计combobox需要显示 端口名+(description)

    for (inputProfileMap=m_pVolumeControl->inputPortProfileNameMap.begin();inputProfileMap!= m_pVolumeControl->inputPortProfileNameMap.end();) {
        if (inputProfileMap.key() == index) {
            temp = inputProfileMap.value();
            for(at = temp.begin();at != temp.end();){
                if(at.value() == inputcomboboxPortNameList.at(0)){
                    endInputProfile = at.value();
                }
                ++at;
            }

        }
        ++inputProfileMap;
    }
    if (outputCurrrentItem != nullptr) {
        QMap <QString,QString>::iterator it;
        QMap <QString,QString> temp;
        int index = findCardIndex(outputWid->deviceLabel->text(),m_pVolumeControl->cardMap);
        for (outputProfileMap=m_pVolumeControl->profileNameMap.begin();outputProfileMap!= m_pVolumeControl->profileNameMap.end();) {
            if (outputProfileMap.key() == index) {
                temp = outputProfileMap.value();
                for(it=temp.begin();it!=temp.end();){
                    if(it.key() == comboboxPortNameList.at(0)){
                        endOutputProfile = it.value();
                    }
                    ++it;
                }
            }
            ++outputProfileMap;
        }
    }

    //如果选择的输入输出设备为同一个声卡，则追加指定输入输出端口属于的配置文件
    if (outputCurrrentItem != nullptr && wid->deviceLabel->text() == outputWid->deviceLabel->text()) {
        QString  setProfile;
        //有些声卡的配置文件默认只有输入/输出设备或者配置文件包含了输出输入设备，因此只需要取其中一个配置文件即可
        if (endOutputProfile == "a2dp-sink" || endInputProfile == "headset_head_unit" || endOutputProfile == "HiFi" ) {
            setProfile += endInputProfile;
        }
        else {
            setProfile += endOutputProfile;
            setProfile += "+";
            setProfile +=endInputProfile;
        }
        setCardProfile(wid->deviceLabel->text(),setProfile);
        setDefaultInputPortDevice(wid->deviceLabel->text(),wid->portLabel->fullText);
    }
    //如果选择的输入输出设备不是同一块声卡，需要设置一个优先级高的配置文件
    else {
        int index = findCardIndex(wid->deviceLabel->text(),m_pVolumeControl->cardMap);
        QMap <int,QList<QString>>::iterator it;
        QString profileName;
        for(it=m_pVolumeControl->cardProfileMap.begin();it!=m_pVolumeControl->cardProfileMap.end();) {

            if (it.key() == index) {
                QStringList list= it.value();
                profileName = findHighPriorityProfile(index,endInputProfile);
                if (list.contains(endOutputProfile)) {

                }
            }
            ++it;
        }
        QString  setProfile = profileName;
        setCardProfile(wid->deviceLabel->text(),setProfile);
        setDefaultInputPortDevice(wid->deviceLabel->text(),wid->portLabel->fullText);
    }
    qDebug() << "active input port:" << wid->portLabel->fullText << isCheckBluetoothInput;
}


void UkmediaMainWidget::updateAppVolume(QString str, int value, bool state)
{
    qDebug() << "update app volume" << isFirstRecive << str << value <<state << updateAppVolumeCount;
//    if (isFirstRecive && updateAppVolumeCount == 1) {
//        isFirstRecive = false;
//        return;
//    }
//    else {
//        ++updateAppVolumeCount;
//    }
    bool found = true;

    QSlider *slider = appWidget->findChild<QSlider*>(str);
    if (slider == nullptr) {
        found = false;
    }
    if (found) {
        kylinVideoVolumeSignal = true;
        if(slider->value() == value)
            kylinVideoVolumeSignal = false;
        slider->setValue(value);
    }
    else
        value = -1;
    qDebug() << "found app slider, set value ----" << value;

    QPushButton *btn = appWidget->findChild<QPushButton*>(str);
    if (btn == nullptr) {
        found = false;
    }
    else {
        qDebug() << "founded  app mute button ------------" << str << state;
        isAppMuteBtnPress = true;
        sinkInputMute = state;
        kylinVideoMuteSignal = true;
        btn->setChecked(true);
        btn->click();
    }

    QDBusMessage message =QDBusMessage::createSignal("/", "org.ukui.media", "sinkVolumeChanged");
    message<<str<<value<<state;
    QDBusConnection::sessionBus().send(message);
    qDebug() <<"sinkVolumeChanged11111111111" <<str <<value <<state;
}

/*
 * 添加output port到output list widget
 */
void UkmediaMainWidget::addOutputListWidgetItem(QString portName, QString portLabel, QString cardName)
{
    UkuiListWidgetItem *itemW = new UkuiListWidgetItem(this);
    int i = systemWidget->m_pOutputListWidget->count();
    QListWidgetItem * item = new QListWidgetItem(systemWidget->m_pOutputListWidget);
    item->setSizeHint(QSize(200,48)); //QSize(120, 40) spacing: 12px;
    systemWidget->m_pOutputListWidget->blockSignals(true);
    systemWidget->m_pOutputListWidget->setItemWidget(item, itemW);
    systemWidget->m_pOutputListWidget->blockSignals(false);
    itemW->setLabelText(portLabel,cardName);
    itemW->setButtonIcon(portName);
    systemWidget->m_pOutputListWidget->blockSignals(true);
    systemWidget->m_pOutputListWidget->insertItem(i,item);
    updateOutputListWidgetFont();
    systemWidget->m_pOutputListWidget->blockSignals(false);
}

void UkmediaMainWidget::setDeviceButtonState(int row)
{
    for (int i=0;i<systemWidget->m_pOutputListWidget->count();i++) {
        if (i == row)
            continue;
        QListWidgetItem *item = systemWidget->m_pOutputListWidget->item(i);
        UkuiListWidgetItem *wid = (UkuiListWidgetItem *)systemWidget->m_pOutputListWidget->itemWidget(item);
        wid->deviceButton->buttonState = PUSH_BUTTON_NORMAL;
        wid->deviceButton->setActive(false);
    }
}

/*
 * 添加input port到input list widget
 */
void UkmediaMainWidget::addInputListWidgetItem(QString portName, QString cardName)
{
    UkuiListWidgetItem *itemW = new UkuiListWidgetItem(this);
    int i = systemWidget->m_pInputListWidget->count();
    QListWidgetItem * item = new QListWidgetItem(systemWidget->m_pInputListWidget);
    item->setSizeHint(QSize(200,48)); //QSize(120, 40) spacing: 12px;
    systemWidget->m_pInputListWidget->blockSignals(true);
    systemWidget->m_pInputListWidget->setItemWidget(item, itemW);
    systemWidget->m_pInputListWidget->blockSignals(false);
    itemW->setLabelText(portName,cardName);
    itemW->setButtonIcon(portName);
    systemWidget->m_pInputListWidget->blockSignals(true);
    systemWidget->m_pInputListWidget->insertItem(i,item);
    systemWidget->m_pInputListWidget->blockSignals(false);
}

int UkmediaMainWidget::indexOfOutputPortInOutputListWidget(QString portName)
{
    for (int row=0;row<systemWidget->m_pOutputListWidget->count();row++) {

        QListWidgetItem *item = systemWidget->m_pOutputListWidget->item(row);
        UkuiListWidgetItem *wid = (UkuiListWidgetItem *)systemWidget->m_pOutputListWidget->itemWidget(item);
        if (wid->portLabel->fullText == portName) {
            return row;
        }
    }
    return -1;
}

int UkmediaMainWidget::indexOfInputPortInInputListWidget(QString portName)
{
    for (int row=0;row<systemWidget->m_pInputListWidget->count();row++) {

        QListWidgetItem *item = systemWidget->m_pInputListWidget->item(row);
        UkuiListWidgetItem *wid = (UkuiListWidgetItem *)systemWidget->m_pInputListWidget->itemWidget(item);
        if (wid->portLabel->fullText == portName) {
            return row;
        }
    }
    return -1;
}

/*
 * 当前的输出端口是否应该在output list widget上删除
 */
bool UkmediaMainWidget::outputPortIsNeedDelete(int index, QString name)
{
    QMap<int,QMap<QString,QString>>::iterator it;
    QMap<QString,QString>::iterator at;
    QMap<QString,QString> portMap;
//    qDebug() << "outputPortIsNeedDelete" << index << name;
    for(it = m_pVolumeControl->outputPortMap.begin();it!=m_pVolumeControl->outputPortMap.end();)
    {
        if (it.key() == index) {
            portMap = it.value();
            for (at=portMap.begin();at!=portMap.end();) {
                if (name == at.value()) {
                    return false;
                }
                ++at;
            }
        }
        ++it;
    }
    return true;
}

/*
 * 当前的输出端口是否应该添加到output list widget上
 */
bool UkmediaMainWidget::outputPortIsNeedAdd(int index, QString name)
{
    QMap<int,QString>::iterator it;
    for(it=currentOutputPortLabelMap.begin();it!=currentOutputPortLabelMap.end();) {
        if ( index == it.key() && name == it.value()) {
            return false;
        }
        ++it;
    }
    return true;
}

/*
 * 当前的输出端口是否应该在input list widget上删除
 */
bool UkmediaMainWidget::inputPortIsNeedDelete(int index, QString name)
{
    QMap<int,QMap<QString,QString>>::iterator it;
    QMap<QString,QString>::iterator at;
    QMap<QString,QString> portMap;
    for(it = m_pVolumeControl->inputPortMap.begin();it!=m_pVolumeControl->inputPortMap.end();)
    {
        if (it.key() == index) {
            portMap = it.value();
            for (at=portMap.begin();at!=portMap.end();) {
                if (name == at.value()) {
                    return false;
                }
                ++at;
            }
        }
        ++it;
    }
    return true;
}

/*
 * 当前的输出端口是否应该添加到input list widget上
 */
bool UkmediaMainWidget::inputPortIsNeedAdd(int index, QString name)
{
    QMap<int,QString>::iterator it;
    for(it=currentInputPortLabelMap.begin();it!=currentInputPortLabelMap.end();) {
        if ( index == it.key() && name == it.value()) {
            return false;
        }
        ++it;
    }
    return true;
}


/*
 * 移除output list widget上不可用的输出端口
 */
void UkmediaMainWidget::deleteNotAvailableOutputPort()
{
    qDebug() << "deleteNotAvailableOutputPort";
    //删除不可用的输出端口
    QMap<int,QString>::iterator it;
    for(it=currentOutputPortLabelMap.begin();it!=currentOutputPortLabelMap.end();) {
        //没找到，需要删除
        if (outputPortIsNeedDelete(it.key(),it.value())) {
            qDebug() << "outputPortIsNeedDelete" << it.key() << it.value();
            int index = indexOfOutputPortInOutputListWidget(it.value());
            if (index == -1)
                return;
            systemWidget->m_pOutputListWidget->blockSignals(true);
            QListWidgetItem *item = systemWidget->m_pOutputListWidget->takeItem(index);
            systemWidget->m_pOutputListWidget->removeItemWidget(item);
            systemWidget->m_pOutputListWidget->blockSignals(false);
            it = currentOutputPortLabelMap.erase(it);
            continue;
        }
        ++it;
    }
//    m_pVolumeControl->removeProfileMap();

}


/*
 * 添加可用的输出端口到output list widget
 */
void UkmediaMainWidget::addAvailableOutputPort()
{
    QMap<int,QMap<QString,QString>>::iterator at;
    QMap<QString,QString>::iterator it;
    QMap<QString,QString> tempMap;
    int i = systemWidget->m_pOutputListWidget->count();
    //增加端口
    for(at=m_pVolumeControl->outputPortMap.begin();at!=m_pVolumeControl->outputPortMap.end();)
    {
        tempMap = at.value();
//        qDebug() << "addAvailableOutputPort" << at.key() <<at.value();
        for (it=tempMap.begin();it!=tempMap.end();) {
            //需添加到list widget
            if (outputPortIsNeedAdd(at.key(),it.value())) {
                qDebug() << "add output list widget" << at.key()<< it.value() << it.key();
                UkuiListWidgetItem *itemW = new UkuiListWidgetItem(this);

                QListWidgetItem * item = new QListWidgetItem(systemWidget->m_pOutputListWidget);
                item->setSizeHint(QSize(200,48)); //QSize(120, 40) spacing: 12px;
                systemWidget->m_pOutputListWidget->blockSignals(true);
                systemWidget->m_pOutputListWidget->setItemWidget(item, itemW);
                systemWidget->m_pOutputListWidget->blockSignals(false);

                itemW->setLabelText(it.value(),findCardName(at.key(),m_pVolumeControl->cardMap));
                itemW->setButtonIcon(it.key());
                itemW->deviceButton->setActive(false);
                currentOutputPortLabelMap.insertMulti(at.key(),it.value());
                systemWidget->m_pOutputListWidget->blockSignals(true);
                systemWidget->m_pOutputListWidget->insertItem(i,item);
                updateOutputListWidgetFont();
                systemWidget->m_pOutputListWidget->blockSignals(false);
            }
            ++it;
        }
        ++at;
    }
}

/*
 * 在input list widget删除不可用的端口
 */
void UkmediaMainWidget::deleteNotAvailableInputPort()
{
    //删除不可用的输入端口
    QMap<int,QString>::iterator it;
    for(it=currentInputPortLabelMap.begin();it!=currentInputPortLabelMap.end();) {
        //没找到，需要删除
        if (inputPortIsNeedDelete(it.key(),it.value())) {
            int index = indexOfInputPortInInputListWidget(it.value());
            if (index == -1)
                return;
            systemWidget->m_pInputListWidget->blockSignals(true);
            QListWidgetItem *item = systemWidget->m_pInputListWidget->takeItem(index);
            systemWidget->m_pInputListWidget->removeItemWidget(item);
            systemWidget->m_pInputListWidget->blockSignals(false);
            it = currentInputPortLabelMap.erase(it);
            continue;
        }
        ++it;
    }
//    m_pVolumeControl->removeInputProfile();
}

/*
 *  添加可用的输入端口到input list widget
 */
void UkmediaMainWidget::addAvailableInputPort()
{
    QMap<int,QMap<QString,QString>>::iterator at;
    QMap<QString,QString>::iterator it;
    QMap<QString,QString> tempMap;
    int i = systemWidget->m_pInputListWidget->count();
    //增加端口
    for(at=m_pVolumeControl->inputPortMap.begin();at!=m_pVolumeControl->inputPortMap.end();)
    {
        tempMap = at.value();
        for (it=tempMap.begin();it!=tempMap.end();) {
            //需添加到list widget
            if (inputPortIsNeedAdd(at.key(),it.value())) {
                UkuiListWidgetItem *itemW = new UkuiListWidgetItem(this);
                QListWidgetItem * item = new QListWidgetItem(systemWidget->m_pInputListWidget);
                item->setSizeHint(QSize(200,48)); //QSize(120, 40) spacing: 12px;
                systemWidget->m_pInputListWidget->blockSignals(true);
                systemWidget->m_pInputListWidget->setItemWidget(item, itemW);
                systemWidget->m_pInputListWidget->blockSignals(false);

                itemW->setLabelText(it.value(),findCardName(at.key(),m_pVolumeControl->cardMap));
                currentInputPortLabelMap.insertMulti(at.key(),it.value());
                systemWidget->m_pInputListWidget->blockSignals(true);
                systemWidget->m_pInputListWidget->insertItem(i,item);
                systemWidget->m_pInputListWidget->blockSignals(false);
            }
            ++it;
        }
        ++at;
    }
}


//查找指定声卡名的索引
int UkmediaMainWidget::findCardIndex(QString cardName, QMap<int,QString> cardMap)
{
    QMap<int, QString>::iterator it;

    for(it=cardMap.begin();it!=cardMap.end();) {
        if (it.value() == cardName) {
            return it.key();
        }
        ++it;
    }
    return -1;
}

/*
 * 根据声卡索引查找声卡名
 */
QString UkmediaMainWidget::findCardName(int index,QMap<int,QString> cardMap)
{
    QMap<int, QString>::iterator it;

    for(it=cardMap.begin();it!=cardMap.end();) {
        if (it.key() == index) {
            return it.value();
        }
        ++it;
    }
    return "";
}

QString UkmediaMainWidget::findHighPriorityProfile(int index,QString profile)
{
    QMap<int, QMap<QString,int>>::iterator it;
    int priority = 0;
    QString profileName = "";
    QMap<QString,int> profileNameMap;
    QMap<QString,int>::iterator tempMap;
    QString cardStr = findCardName(index,m_pVolumeControl->cardMap);

    QString profileStr = findCardActiveProfile(index) ;

    QStringList list = profileStr.split("+");
    QString includeProfile = "";

    if (list.count() >1) {
        if (profile.contains("output")) {
            includeProfile = list.at(1);
        }
        else if (profile.contains("input")){
            includeProfile = list.at(0);
        }
        qDebug() << "profile str" <<profile <<"0:"<<list.at(0) <<"1:"<<list.at(1) <<list.count() <<includeProfile;
    }
    else {
        includeProfile = list.at(0);
    }
    for (it=m_pVolumeControl->cardProfilePriorityMap.begin();it!=m_pVolumeControl->cardProfilePriorityMap.end();) {
        if (it.key() == index) {
            profileNameMap = it.value();
            for (tempMap=profileNameMap.begin();tempMap!=profileNameMap.end();) {
//                qDebug() << "findHighPriorityProfile" << includeProfile <<tempMap.key() << profile;
                if (includeProfile != "" && tempMap.key().contains(includeProfile)  && !tempMap.key().contains(includeProfile+"-") \
                        && tempMap.key().contains(profile) && !tempMap.key().contains(profile+"-")) {
                    priority = tempMap.value();
                    profileName = tempMap.key();
                }
                else if ( tempMap.key().contains(profile) && tempMap.value() > priority) {
                    priority = tempMap.value();
                    profileName = tempMap.key();
                }
                ++tempMap;
            }
        }
        ++it;
    }
    qDebug() << "profile str----------" <<profileStr <<profileName << profile << includeProfile;
    return profileName;
}

/*
 * Find the corresponding sink according to the port name
 */
QString UkmediaMainWidget::findPortSink(int index,QString portName)
{
    QMap<int, QMap<QString,QString>>::iterator it;
    QMap<QString,QString> portNameMap;
    QMap<QString,QString>::iterator tempMap;
    QString sinkStr = "";
    for (it=m_pVolumeControl->sinkPortMap.begin();it!=m_pVolumeControl->sinkPortMap.end();) {
        if(it.key() == index) {
            portNameMap = it.value();
            for (tempMap=portNameMap.begin();tempMap!=portNameMap.end();) {
                if (tempMap.value() == portName) {
                    sinkStr = tempMap.key();
//                    qDebug() <<"find port sink" << tempMap.value() << portName << tempMap.key() <<sinkStr;
                    break;
                }
                ++tempMap;
            }
        }

        ++it;
    }
    if(sinkStr == "")
        qDebug() << "sinkStr not found ---";

    return sinkStr;
}

/*
 * Find the corresponding source according to the port name
 */
QString UkmediaMainWidget::findPortSource(int index,QString portName)
{
    QMap<int, QMap<QString,QString>>::iterator it;
    QMap<QString,QString> portNameMap;
    QMap<QString,QString>::iterator tempMap;
    QString sourceStr = "";
    for (it=m_pVolumeControl->sourcePortMap.begin();it!=m_pVolumeControl->sourcePortMap.end();) {
        if(it.key() == index) {
            portNameMap = it.value();
            for (tempMap=portNameMap.begin();tempMap!=portNameMap.end();) {
                qDebug() << "findportsource ===" <<tempMap.value() << portName;
                if ( tempMap.value() == portName) {
                    sourceStr = tempMap.key();
                    break;
                }
                ++tempMap;
            }
        }
        ++it;
    }
    return sourceStr;
}

/*
    查找名称为PortLbael 的portName
*/
QString UkmediaMainWidget::findOutputPortName(int index,QString portLabel)
{
    QMap<int, QMap<QString,QString>>::iterator it;
    QMap<QString,QString>portMap;
    QMap<QString,QString>::iterator tempMap;
    QString portName = "";
    for (it = m_pVolumeControl->outputPortMap.begin();it != m_pVolumeControl->outputPortMap.end();) {
        if (it.key() == index) {
            portMap = it.value();
            for (tempMap = portMap.begin();tempMap!=portMap.end();) {
                if (tempMap.value() == portLabel) {
                    portName = tempMap.key();
                    break;
                }
                ++tempMap;
            }
        }
        ++it;
    }
    return portName;
}

/*
    查找名称为PortName 的portLabel
*/
QString UkmediaMainWidget::findOutputPortLabel(int index,QString portName)
{
    QMap<int, QMap<QString,QString>>::iterator it;
    QMap<QString,QString>portMap;
    QMap<QString,QString>::iterator tempMap;
    QString portLabel = "";
    for (it = m_pVolumeControl->outputPortMap.begin();it != m_pVolumeControl->outputPortMap.end();) {
        if (it.key() == index) {
            portMap = it.value();
            for (tempMap = portMap.begin();tempMap!=portMap.end();) {
//                qDebug() <<"findOutputPortLabel" <<portName <<tempMap.key() <<tempMap.value();
                if (tempMap.key() == portName) {
                    portLabel = tempMap.value();
                    break;
                }
                ++tempMap;
            }
        }
        ++it;
    }
    return portLabel;
}

/*
    查找名称为PortLbael 的portName
*/
QString UkmediaMainWidget::findInputPortName(int index,QString portLabel)
{
    QMap<int, QMap<QString,QString>>::iterator it;
    QMap<QString,QString>portMap;
    QMap<QString,QString>::iterator tempMap;
    QString portName = "";
    for (it = m_pVolumeControl->inputPortMap.begin();it != m_pVolumeControl->inputPortMap.end();) {
        if (it.key() == index) {
            portMap = it.value();
            for (tempMap = portMap.begin();tempMap!=portMap.end();) {
                if (tempMap.value() == portLabel) {
                    portName = tempMap.key();
                    break;
                }
                ++tempMap;
            }
        }
        ++it;
    }
    return portName;
}

/*
    查找名称为PortName 的portLabel
*/
QString UkmediaMainWidget::findInputPortLabel(int index,QString portName)
{
    QMap<int, QMap<QString,QString>>::iterator it;
    QMap<QString,QString>portMap;
    QMap<QString,QString>::iterator tempMap;
    QString portLabel = "";
    for (it = m_pVolumeControl->inputPortMap.begin();it != m_pVolumeControl->inputPortMap.end();) {
        if (it.key() == index) {
            portMap = it.value();
            for (tempMap = portMap.begin();tempMap!=portMap.end();) {
                if (tempMap.key() == portName) {
                    portLabel = tempMap.value();
                    break;
                }
                ++tempMap;
            }
        }
        ++it;
    }
    return portLabel;
}

/*
 *  设置声卡的配置文件
 */
void UkmediaMainWidget::setCardProfile(QString name, QString profile)
{
    int index = findCardIndex(name,m_pVolumeControl->cardMap);
    m_pVolumeControl->setCardProfile(index,profile.toLatin1().data());
}

/*
 * 设置默认的输出设备端口
 */
void UkmediaMainWidget::setDefaultOutputPortDevice(QString devName, QString portName)
{
    int cardIndex = findCardIndex(devName,m_pVolumeControl->cardMap);
    QString portStr = findOutputPortName(cardIndex,portName);
    QTimer *timer = new QTimer;
    timer->start(100);
    connect(timer,&QTimer::timeout,[=](){
        QString sinkStr = findPortSink(cardIndex,portStr);
        /*默认的stream 和设置的stream相同 需要更新端口*/
        if (strcmp(sinkStr.toLatin1().data(),m_pVolumeControl->defaultSinkName) == 0) {
            m_pVolumeControl->setSinkPort(sinkStr.toLatin1().data(),portStr.toLatin1().data());
        }
        else {
            m_pVolumeControl->setDefaultSink(sinkStr.toLatin1().data());
            m_pVolumeControl->setSinkPort(sinkStr.toLatin1().data(),portStr.toLatin1().data());
        }
        qDebug() << "setDefaultOutputPortDevice" << "cardIndex:" << cardIndex << "portStr:" << portStr << "sinkStr:" << sinkStr;
        /*
            bug:94489 修复选择默认设备时不弹osd弹窗问题
        */
        if (portStr.contains("speaker",Qt::CaseInsensitive))
        {
            Q_EMIT m_pVolumeControl->device_changed_signal("audio-volume-high-symbolic");
        }
        else
        {
            if(portStr!="")
                Q_EMIT m_pVolumeControl->device_changed_signal("ukui-headset-symbolic");
        }

        delete timer;
    });
}

/*
 * 设置默认的输入设备端口
 */
void UkmediaMainWidget::setDefaultInputPortDevice(QString devName, QString portName)
{
    int cardIndex = findCardIndex(devName,m_pVolumeControl->cardMap);
    QString portStr = findInputPortName(cardIndex,portName);
    QString sourceStr = findPortSource(cardIndex,portStr);

    /*默认的stream 和设置的stream相同 需要更新端口*/
    if (strcmp(sourceStr.toLatin1().data(),m_pVolumeControl->defaultSourceName) == 0) {
        m_pVolumeControl->setSourcePort(sourceStr.toLatin1().data(),portStr.toLatin1().data());
    }
    else {
        m_pVolumeControl->setDefaultSource(sourceStr.toLatin1().data());
        m_pVolumeControl->setSourcePort(sourceStr.toLatin1().data(),portStr.toLatin1().data());
    }
    qDebug() << "set default input"  << portName <<cardIndex;
}

/*
 * 查找指定索引声卡的active profile
 */
QString UkmediaMainWidget::findCardActiveProfile(int index)
{
    QString activeProfileName = "";
    QMap<int,QString>::iterator it;
    for (it=m_pVolumeControl->cardActiveProfileMap.begin();it!=m_pVolumeControl->cardActiveProfileMap.end();) {
        if (it.key() == index) {
            activeProfileName = it.value();
            break;
        }
        ++it;
    }
    return activeProfileName;
}

void UkmediaMainWidget::findOutputListWidgetItem(QString cardName,QString portLabel)
{
    for (int row=0;row<systemWidget->m_pOutputListWidget->count();row++) {

        QListWidgetItem *item = systemWidget->m_pOutputListWidget->item(row);
        UkuiListWidgetItem *wid = (UkuiListWidgetItem *)systemWidget->m_pOutputListWidget->itemWidget(item);
        qDebug() << "findOutputListWidgetItem" << "cardName:" << cardName << wid->deviceLabel->text() << "portName:" << portLabel << wid->portLabel->fullText;
        if (wid->deviceLabel->text() == cardName && portLabel == wid->portLabel->fullText) {
            systemWidget->m_pOutputListWidget->blockSignals(true);
            systemWidget->m_pOutputListWidget->setCurrentRow(row);
            wid->deviceButton->buttonState = PUSH_BUTTON_CLICK;
            wid->deviceButton->setActive(true);
            setDeviceButtonState(row);
            systemWidget->m_pOutputListWidget->blockSignals(false);
            wid->deviceButton->repaint();
            break;
        }
    }
    if(!m_pVolumeControl->customSoundFile->isExist(m_pVolumeControl->sinkPortName) && m_pVolumeControl->sinkPortName != "")
        QTimer::singleShot(50, this, SLOT(initDefaultSinkVolume()));
}

void UkmediaMainWidget::findInputListWidgetItem(QString cardName,QString portLabel)
{
    //增加输入设备插入拔出信号

    QDBusMessage message = QDBusMessage::createSignal("/","org.ukui.media","sourcePortChanged");
    message << "portChanged";
    QDBusConnection::sessionBus().send(message);
    qDebug() << "sourcePortChanged" << endl;

    for (int row=0;row<systemWidget->m_pInputListWidget->count();row++) {
        QListWidgetItem *item = systemWidget->m_pInputListWidget->item(row);
        UkuiListWidgetItem *wid = (UkuiListWidgetItem *)systemWidget->m_pInputListWidget->itemWidget(item);
        qDebug() << "findInputListWidgetItem" << "card name:" << cardName << "deviceLabel:" << wid->deviceLabel->text() << "portname" << portLabel << "portLabel:" << wid->portLabel->fullText ;
        if (wid->deviceLabel->text() == cardName && wid->portLabel->fullText == portLabel) {
            systemWidget->m_pInputListWidget->blockSignals(true);
            systemWidget->m_pInputListWidget->setCurrentRow(row);
            systemWidget->m_pInputListWidget->blockSignals(false);
            if (wid->deviceLabel->text().contains("bluez_card"))
                isCheckBluetoothInput = true;
            qDebug() << "set input list widget" << row;
            break;
        }
    }
    if(!m_pVolumeControl->customSoundFile->isExist(m_pVolumeControl->sourcePortName) && m_pVolumeControl->sourcePortName != "")
        QTimer::singleShot(50, this, SLOT(initDefaultSourceVolume()));
}

/*
 * 输入设备中是否包含蓝牙设备
 */
bool UkmediaMainWidget::inputDeviceContainBluetooth()
{
    for (int row=0;row<systemWidget->m_pInputListWidget->count();row++) {

        QListWidgetItem *item = systemWidget->m_pInputListWidget->item(row);
        UkuiListWidgetItem *wid = (UkuiListWidgetItem *)systemWidget->m_pInputListWidget->itemWidget(item);
        if (wid->deviceLabel->text().contains("bluez")) {
            return true;
        }
    }
    return false;
}

/*
 * 移除xml文件中不能识别的字符
 */
QString UkmediaMainWidget::stringRemoveUnrecignizedChar(QString str)
{
    str.remove(" ");
    str.remove("/");
    str.remove("(");
    str.remove(")");
    str.remove("[");
    str.remove("]");
    return str;
}


QString UkmediaMainWidget::blueCardName()
{
    for (int row=0;row<systemWidget->m_pInputListWidget->count();row++) {

        QListWidgetItem *item = systemWidget->m_pInputListWidget->item(row);
        UkuiListWidgetItem *wid = (UkuiListWidgetItem *)systemWidget->m_pInputListWidget->itemWidget(item);
        if (wid->deviceLabel->text().contains("bluez")) {
            return wid->deviceLabel->text();
        }
    }
    return "";
}

/**
 * @brief MainWindow::keyPressEvent 按esc键关闭主界面
 * @param event
 */
void UkmediaMainWidget::keyPressEvent(QKeyEvent *event)
{
    if (event->key() == Qt::Key_Escape) {
        hideWindow();
    }
    return QWidget::keyPressEvent(event);
}

/*
 *在path路径下找包含str字段的文件名(暂时用来寻找wine微信)
 */
QString UkmediaMainWidget::findFile(const QString path,QString str)
{
    QDir dir(path);
    QString filename = "";
    if(!dir.exists())
    {
        return "";
    }

    //获取filePath下所有文件夹和文件
    dir.setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);//文件夹|文件|不包含./和../

    //排序文件夹优先
    dir.setSorting(QDir::DirsFirst);

    QStringList filer;
    QStringList list= dir.entryList(filer, QDir::Files | QDir::NoDotAndDotDot);

    if(list.size() == 0)
    {
        return "";
    }

    for(int i = 0; i < list.size(); i++)
    {
        QFileInfo fileInfo = list.at(i);
        if(fileInfo.isDir())//判断是否为文件夹
        {
            findFile(fileInfo.filePath(),str);//递归开始
        }
        else
        {
            if(fileInfo.fileName().contains(str) && !fileInfo.fileName().contains("企业微信") && !fileInfo.fileName().contains("卸载微信"))//设定后缀
            {
                filename = fileInfo.fileName();
                qDebug() << "在/usr/share/applications/找到文件" << filename;
                break;
            }
        }
    }
    return filename;
}

void UkmediaMainWidget::inhibit()
{
    if (m_inhibitFileDescriptor.isValid()) {
        return;
    }

    QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.login1",
                                                          "/org/freedesktop/login1",
                                                          "org.freedesktop.login1.Manager",
                                                          QStringLiteral("Inhibit"));
    message.setArguments(QVariantList({QStringLiteral("sleep"),
                                       "Screen Locker",
                                       "Ensuring that the screen gets locked before going to sleep",
                                       QStringLiteral("delay")}));
    QDBusPendingReply<QDBusUnixFileDescriptor> reply = QDBusConnection::systemBus().call(message);
    if (!reply.isValid()) {
        return;
    }
    reply.value().swap(m_inhibitFileDescriptor);
}

void UkmediaMainWidget::uninhibit()
{
    if (!m_inhibitFileDescriptor.isValid()) {
        return;
    }
    m_inhibitFileDescriptor = QDBusUnixFileDescriptor();
}

void UkmediaMainWidget::switchModuleEchoCancel()
{
    bool sourceState = false;
    bool switchState = false;
    if (m_pSoundSettings->keys().contains("dnsNoiseReduction")) {
        switchState = m_pSoundSettings->get(DNS_NOISE_REDUCTION).toBool();
    }
    if ( strstr(m_pVolumeControl->defaultSourceName,"alsa_input") && !strstr(m_pVolumeControl->defaultSourceName,"input.usb")) {
        sourceState = true;
     }
    qDebug() << "switchModuleEchoCancel" << m_pVolumeControl->defaultSourceName << switchState << sourceState;
    if (switchState && sourceState && !isLoadEchoCancel && !strstr(m_pVolumeControl->defaultSourceName,"noiseReduceSource")) {
        pa_operation *o;
        qDebug() << "load module echo cancel";
        isLoadEchoCancel = true;
        if (!(o=pa_context_load_module(m_pVolumeControl->getContext(),"module-echo-cancel","use_master_format=1 aec_method=webrtc aec_args=analog_gain_control=0 source_name=noiseReduceSource",nullptr,nullptr))) {
                m_pVolumeControl->showError(QObject::tr("pa_context_load_module() failed").toUtf8().constData());
        }
    }
    else if (isLoadEchoCancel && !switchState) {
        isLoadEchoCancel = false;
        m_pVolumeControl->getModuleIndexByName("module-echo-cancel");

        QTimer::singleShot(300,this,[=](){
            qDebug() << "unload module echo cancel" << m_pVolumeControl->findModuleIndex;
            pa_context_unload_module(m_pVolumeControl->getContext(),m_pVolumeControl->findModuleIndex,nullptr,nullptr);
        });
    }
}

void UkmediaMainWidget::resetVolumeSliderRange()
{
    if (m_pSoundSettings->keys().contains("volumeIncrease")) {
        if(m_pSoundSettings->get(VOLUME_INCREASE).toBool()) {
            systemWidget->m_pSystemVolumeSlider->setRange(0,125);
            appWidget->systemVolumeSlider->setRange(0,125);
        }
        else {
            systemWidget->m_pSystemVolumeSlider->setRange(0,100);
            appWidget->systemVolumeSlider->setRange(0,100);
        }
    }
}

UkmediaMainWidget::~UkmediaMainWidget()
{

}
