mirror of
https://github.com/linuxdeepin/dde-dock.git
synced 2025-06-03 00:15:21 +00:00
feat: 将音乐播放功能提取为单独的插件
将dock中的音乐播放功能提取为音乐插件 Log: Influence: 无 Task: https://pms.uniontech.com/task-view-220489.html Change-Id: Ie58d1645fff08332a03398aa8ce9cb0e90f16ad2
This commit is contained in:
parent
3edc83802b
commit
6d14fd1be7
51
plugins/media/CMakeLists.txt
Normal file
51
plugins/media/CMakeLists.txt
Normal file
@ -0,0 +1,51 @@
|
||||
|
||||
set(PLUGIN_NAME "media")
|
||||
|
||||
project(${PLUGIN_NAME})
|
||||
|
||||
generation_dbus_interface(${CMAKE_CURRENT_SOURCE_DIR}/dbusinterface/xml ${CMAKE_CURRENT_SOURCE_DIR}/dbusinterface/generation_dbus_interface)
|
||||
|
||||
# Sources files
|
||||
file(GLOB_RECURSE SRCS "*.h" "*.cpp"
|
||||
"../../widgets/*.h"
|
||||
"../../widgets/*.cpp"
|
||||
"../../frame/util/imageutil.h"
|
||||
"../../frame/util/imageutil.cpp"
|
||||
"../../frame/util/statebutton.h"
|
||||
"../../frame/util/statebutton.cpp"
|
||||
"../../frame/util/horizontalseperator.h"
|
||||
"../../frame/util/horizontalseperator.cpp"
|
||||
"../../frame/qtdbusextended/*.h"
|
||||
"../../frame/qtdbusextended/*.cpp")
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
find_package(Qt5Svg REQUIRED)
|
||||
find_package(Qt5DBus REQUIRED)
|
||||
find_package(DtkWidget REQUIRED)
|
||||
|
||||
pkg_check_modules(XCB_EWMH REQUIRED xcb-ewmh x11 xcursor)
|
||||
pkg_check_modules(QGSettings REQUIRED gsettings-qt)
|
||||
|
||||
add_definitions("${QT_DEFINITIONS} -DQT_PLUGIN")
|
||||
add_library(${PLUGIN_NAME} SHARED ${SRCS})
|
||||
set_target_properties(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../quick-trays)
|
||||
target_include_directories(${PLUGIN_NAME} PUBLIC ${DtkWidget_INCLUDE_DIRS}
|
||||
${QGSettings_INCLUDE_DIRS}
|
||||
../../interfaces
|
||||
../../widgets
|
||||
../../frame
|
||||
../../frame/qtdbusextended
|
||||
./dbusinterface/generation_dbus_interface
|
||||
componments)
|
||||
|
||||
target_link_libraries(${PLUGIN_NAME} PRIVATE
|
||||
${XCB_EWMH_LIBRARIES}
|
||||
${DtkWidget_LIBRARIES}
|
||||
${QGSettings_LIBRARIES}
|
||||
${Qt5DBus_LIBRARIES}
|
||||
${Qt5Widgets_LIBRARIES}
|
||||
${Qt5Svg_LIBRARIES}
|
||||
)
|
||||
|
||||
install(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION lib/dde-dock/plugins/quick-trays)
|
3
plugins/media/media.json
Normal file
3
plugins/media/media.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"api": "2.0.0"
|
||||
}
|
252
plugins/media/mediaplayermodel.cpp
Normal file
252
plugins/media/mediaplayermodel.cpp
Normal file
@ -0,0 +1,252 @@
|
||||
#include "mediaplayermodel.h"
|
||||
|
||||
#include <QDBusConnectionInterface>
|
||||
#include <QDBusInterface>
|
||||
#include <QDBusPendingCall>
|
||||
#include <QDBusReply>
|
||||
#include <QDebug>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QMetaMethod>
|
||||
#include <QDBusAbstractInterface>
|
||||
|
||||
MediaPlayerModel::MediaPlayerModel(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_isActived(false)
|
||||
, m_mediaInter(nullptr)
|
||||
{
|
||||
initMediaPlayer();
|
||||
}
|
||||
|
||||
MediaPlayerModel::~MediaPlayerModel()
|
||||
{
|
||||
}
|
||||
|
||||
bool MediaPlayerModel::isActived()
|
||||
{
|
||||
return m_isActived;
|
||||
}
|
||||
|
||||
bool MediaPlayerModel::canGoNext()
|
||||
{
|
||||
return m_mediaInter ? m_mediaInter->canGoNext() : false;
|
||||
}
|
||||
|
||||
bool MediaPlayerModel::canGoPrevious()
|
||||
{
|
||||
return m_mediaInter ? m_mediaInter->canGoPrevious() : false;
|
||||
}
|
||||
|
||||
bool MediaPlayerModel::canPause()
|
||||
{
|
||||
return m_mediaInter ? m_mediaInter->canPause() : false;
|
||||
}
|
||||
|
||||
MediaPlayerModel::PlayStatus MediaPlayerModel::status()
|
||||
{
|
||||
if (!m_isActived || !m_mediaInter)
|
||||
return PlayStatus::Stop;
|
||||
|
||||
return convertStatus(m_mediaInter->playbackStatus());
|
||||
}
|
||||
|
||||
const QString MediaPlayerModel::name()
|
||||
{
|
||||
if (m_mediaInter) {
|
||||
Dict data = m_mediaInter->metadata();
|
||||
return data["xesam:title"].toString();
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
const QString MediaPlayerModel::iconUrl()
|
||||
{
|
||||
if (m_mediaInter) {
|
||||
Dict data = m_mediaInter->metadata();
|
||||
return data["mpris:artUrl"].toString();
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
const QString MediaPlayerModel::album()
|
||||
{
|
||||
if (m_mediaInter) {
|
||||
Dict data = m_mediaInter->metadata();
|
||||
return data["xesam:album"].toString();
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
const QString MediaPlayerModel::artist()
|
||||
{
|
||||
if (m_mediaInter) {
|
||||
Dict data = m_mediaInter->metadata();
|
||||
return data["xesam:artist"].toString();
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
void MediaPlayerModel::setStatus(const MediaPlayerModel::PlayStatus &stat)
|
||||
{
|
||||
if (!m_mediaInter)
|
||||
return;
|
||||
|
||||
switch (stat) {
|
||||
case MediaPlayerModel::PlayStatus::Play: {
|
||||
m_mediaInter->Play();
|
||||
break;
|
||||
}
|
||||
case MediaPlayerModel::PlayStatus::Stop: {
|
||||
m_mediaInter->Stop();
|
||||
break;
|
||||
}
|
||||
case MediaPlayerModel::PlayStatus::Pause: {
|
||||
m_mediaInter->Pause();
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
void MediaPlayerModel::playNext()
|
||||
{
|
||||
if (m_mediaInter)
|
||||
m_mediaInter->Next();
|
||||
}
|
||||
|
||||
void MediaPlayerModel::initMediaPlayer()
|
||||
{
|
||||
QDBusInterface dbusInter("org.freedesktop.DBus", "/", "org.freedesktop.DBus", QDBusConnection::sessionBus(), this);
|
||||
QDBusPendingCall call = dbusInter.asyncCall("ListNames");
|
||||
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
|
||||
connect(watcher, &QDBusPendingCallWatcher::finished, [ = ] {
|
||||
m_serviceName.clear();
|
||||
if (call.isError())
|
||||
return;
|
||||
|
||||
QDBusReply<QStringList> reply = call.reply();
|
||||
const QStringList &serviceList = reply.value();
|
||||
|
||||
for (const QString &serv : serviceList) {
|
||||
if (!serv.startsWith("org.mpris.MediaPlayer2"))
|
||||
continue;
|
||||
|
||||
QDBusInterface serviceInterface(serv, "/org/mpris/MediaPlayer2",
|
||||
"org.mpris.MediaPlayer2.Player", QDBusConnection::sessionBus(), this);
|
||||
// 如果开启了谷歌浏览器的后台服务(org.mpris.MediaPlayer2.chromium.instance17352)
|
||||
// 也符合名称要求,但是它不是音乐服务,此时需要判断是否存在这个属性
|
||||
QVariant v = serviceInterface.property("CanPlay");
|
||||
if (!v.isValid() || !v.value<bool>())
|
||||
continue;
|
||||
|
||||
m_serviceName = serv;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!m_serviceName.isEmpty()) {
|
||||
m_isActived = true;
|
||||
|
||||
m_mediaInter = new MediaPlayerInterface(m_serviceName, "/org/mpris/MediaPlayer2", QDBusConnection::sessionBus(), this);
|
||||
connect(m_mediaInter, &MediaPlayerInterface::PlaybackStatusChanged, this, [ this ] {
|
||||
Q_EMIT statusChanged(convertStatus(m_mediaInter->playbackStatus()));
|
||||
});
|
||||
connect(m_mediaInter, &MediaPlayerInterface::MetadataChanged, this, &MediaPlayerModel::metadataChanged);
|
||||
Dict v = m_mediaInter->metadata();
|
||||
m_name = v.value("xesam:title").toString();
|
||||
m_icon = v.value("mpris:artUrl").toString();
|
||||
m_album = v.value("xesam:album").toString();
|
||||
m_artist = v.value("xesam:artist").toString();
|
||||
Q_EMIT startStop(m_isActived);
|
||||
return;
|
||||
}
|
||||
|
||||
QDBusConnectionInterface *dbusInterface = QDBusConnection::sessionBus().interface();
|
||||
connect(dbusInterface, &QDBusConnectionInterface::serviceOwnerChanged, this,
|
||||
[ = ](const QString &name, const QString &, const QString &newOwner) {
|
||||
if (name.startsWith("org.mpris.MediaPlayer2")) {
|
||||
// 启动了音乐播放
|
||||
m_isActived = !newOwner.isEmpty();
|
||||
if (m_isActived) {
|
||||
m_serviceName = name;
|
||||
m_mediaInter = new MediaPlayerInterface(m_serviceName, "/org/mpris/MediaPlayer2", QDBusConnection::sessionBus(), this);
|
||||
connect(m_mediaInter, &MediaPlayerInterface::PlaybackStatusChanged, this, [ this ] {
|
||||
Q_EMIT statusChanged(convertStatus(m_mediaInter->playbackStatus()));
|
||||
});
|
||||
connect(m_mediaInter, &MediaPlayerInterface::MetadataChanged, this, &MediaPlayerModel::metadataChanged);
|
||||
Dict v = m_mediaInter->metadata();
|
||||
m_name = v.value("xesam:title").toString();
|
||||
m_icon = v.value("mpris:artUrl").toString();
|
||||
m_album = v.value("xesam:album").toString();
|
||||
m_artist = v.value("xesam:artist").toString();
|
||||
} else {
|
||||
if (!m_serviceName.isEmpty()) {
|
||||
delete m_mediaInter;
|
||||
m_mediaInter = nullptr;
|
||||
}
|
||||
m_serviceName.clear();
|
||||
}
|
||||
Q_EMIT startStop(m_isActived);
|
||||
}
|
||||
});
|
||||
connect(dbusInterface, &QDBusConnectionInterface::serviceUnregistered, this,
|
||||
[ = ](const QString &service) {
|
||||
if (service.startsWith("org.mpris.MediaPlayer2")) {
|
||||
// 启动了音乐播放
|
||||
m_serviceName.clear();
|
||||
m_isActived = false;
|
||||
Q_EMIT startStop(m_isActived);
|
||||
}
|
||||
});
|
||||
});
|
||||
connect(watcher, &QDBusPendingCallWatcher::finished, watcher, &QDBusPendingCallWatcher::deleteLater);
|
||||
}
|
||||
|
||||
MediaPlayerModel::PlayStatus MediaPlayerModel::convertStatus(const QString &stat)
|
||||
{
|
||||
if (stat == "Paused")
|
||||
return PlayStatus::Pause;
|
||||
if (stat == "Playing")
|
||||
return PlayStatus::Play;
|
||||
if (stat == "Stopped")
|
||||
return PlayStatus::Stop;
|
||||
|
||||
return PlayStatus::Unknow;
|
||||
}
|
||||
|
||||
MediaPlayerInterface::MediaPlayerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
|
||||
: QDBusAbstractInterface(service, path, "org.mpris.MediaPlayer2.Player", connection, parent)
|
||||
{
|
||||
QDBusConnection::sessionBus().connect(this->service(), this->path(), "org.freedesktop.DBus.Properties", "PropertiesChanged", "sa{sv}as", this, SLOT(onPropertyChanged(const QDBusMessage &)));
|
||||
}
|
||||
|
||||
MediaPlayerInterface::~MediaPlayerInterface()
|
||||
{
|
||||
QDBusConnection::sessionBus().disconnect(this->service(), this->path(), "org.freedesktop.DBus.Properties", "PropertiesChanged", "sa{sv}as", this, SLOT(onPropertyChanged(const QDBusMessage &)));
|
||||
}
|
||||
|
||||
void MediaPlayerInterface::onPropertyChanged(const QDBusMessage &msg)
|
||||
{
|
||||
QList<QVariant> arguments = msg.arguments();
|
||||
if (3 != arguments.count())
|
||||
return;
|
||||
|
||||
QString interfaceName = msg.arguments().at(0).toString();
|
||||
if (interfaceName !="org.mpris.MediaPlayer2.Player")
|
||||
return;
|
||||
|
||||
QVariantMap changedProps = qdbus_cast<QVariantMap>(arguments.at(1).value<QDBusArgument>());
|
||||
QStringList keys = changedProps.keys();
|
||||
foreach(const QString &prop, keys) {
|
||||
const QMetaObject* self = metaObject();
|
||||
for (int i = self->propertyOffset(); i < self->propertyCount(); ++i) {
|
||||
QMetaProperty p = self->property(i);
|
||||
if (p.name() == prop) {
|
||||
Q_EMIT p.notifySignal().invoke(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
124
plugins/media/mediaplayermodel.h
Normal file
124
plugins/media/mediaplayermodel.h
Normal file
@ -0,0 +1,124 @@
|
||||
#ifndef MEDIAPLAYERMODEL_H
|
||||
#define MEDIAPLAYERMODEL_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QDBusAbstractInterface>
|
||||
#include <QDBusPendingReply>
|
||||
|
||||
typedef QMap<QString, QVariant> Dict;
|
||||
Q_DECLARE_METATYPE(Dict)
|
||||
|
||||
class QDBusMessage;
|
||||
class QDBusConnection;
|
||||
class MediaPlayerInterface;
|
||||
|
||||
class MediaPlayerModel : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum PlayStatus {
|
||||
Unknow = 0,
|
||||
Play,
|
||||
Pause,
|
||||
Stop
|
||||
};
|
||||
|
||||
public:
|
||||
explicit MediaPlayerModel(QObject *parent = nullptr);
|
||||
~MediaPlayerModel();
|
||||
|
||||
bool isActived();
|
||||
bool canGoNext();
|
||||
bool canGoPrevious();
|
||||
bool canPause();
|
||||
|
||||
PlayStatus status();
|
||||
const QString name();
|
||||
const QString iconUrl();
|
||||
const QString album();
|
||||
const QString artist();
|
||||
|
||||
void setStatus(const PlayStatus &stat);
|
||||
void playNext();
|
||||
|
||||
Q_SIGNALS:
|
||||
void startStop(bool);
|
||||
void statusChanged(const PlayStatus &);
|
||||
void metadataChanged();
|
||||
|
||||
private:
|
||||
void initMediaPlayer();
|
||||
PlayStatus convertStatus(const QString &stat);
|
||||
|
||||
private:
|
||||
bool m_isActived;
|
||||
QString m_serviceName;
|
||||
QString m_name;
|
||||
QString m_icon;
|
||||
QString m_album;
|
||||
QString m_artist;
|
||||
MediaPlayerInterface *m_mediaInter;
|
||||
};
|
||||
|
||||
class MediaPlayerInterface : public QDBusAbstractInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MediaPlayerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);
|
||||
~MediaPlayerInterface();
|
||||
|
||||
public:
|
||||
inline QDBusPendingReply<> Play() {
|
||||
QList<QVariant> argumentList;
|
||||
return asyncCallWithArgumentList(QStringLiteral("Play"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<> Stop() {
|
||||
QList<QVariant> argumentList;
|
||||
return asyncCallWithArgumentList(QStringLiteral("Stop"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<> Pause() {
|
||||
QList<QVariant> argumentList;
|
||||
return asyncCallWithArgumentList(QStringLiteral("Pause"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<> Next() {
|
||||
QList<QVariant> argumentList;
|
||||
return asyncCallWithArgumentList(QStringLiteral("Next"), argumentList);
|
||||
}
|
||||
|
||||
Q_PROPERTY(Dict Metadata READ metadata NOTIFY MetadataChanged)
|
||||
inline Dict metadata() const
|
||||
{ return qvariant_cast<Dict>(property("Metadata")); }
|
||||
|
||||
Q_PROPERTY(bool CanGoNext READ canGoNext NOTIFY CanGoNextChanged)
|
||||
inline bool canGoNext() const
|
||||
{ return qvariant_cast< bool >(property("CanGoNext")); }
|
||||
|
||||
Q_PROPERTY(bool CanGoPrevious READ canGoPrevious NOTIFY CanGoPreviousChanged)
|
||||
inline bool canGoPrevious() const
|
||||
{ return qvariant_cast< bool >(property("CanGoPrevious")); }
|
||||
|
||||
Q_PROPERTY(bool CanPause READ canPause NOTIFY CanPauseChanged)
|
||||
inline bool canPause() const
|
||||
{ return qvariant_cast< bool >(property("CanPause")); }
|
||||
|
||||
Q_PROPERTY(QString PlaybackStatus READ playbackStatus NOTIFY PlaybackStatusChanged)
|
||||
inline QString playbackStatus() const
|
||||
{ return qvariant_cast< QString >(property("PlaybackStatus")); }
|
||||
|
||||
Q_SIGNALS:
|
||||
void MetadataChanged();
|
||||
void CanGoNextChanged();
|
||||
void CanGoPreviousChanged();
|
||||
void CanPauseChanged();
|
||||
void PlaybackStatusChanged();
|
||||
|
||||
private Q_SLOTS:
|
||||
void onPropertyChanged(const QDBusMessage &msg);
|
||||
};
|
||||
|
||||
#endif // MEDIAPLAYERLISTENER_H
|
87
plugins/media/mediaplugin.cpp
Normal file
87
plugins/media/mediaplugin.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: donghualin <donghualin@uniontech.com>
|
||||
*
|
||||
* Maintainer: donghualin <donghualin@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "mediaplugin.h"
|
||||
#include "mediawidget.h"
|
||||
#include "mediaplayermodel.h"
|
||||
|
||||
MediaPlugin::MediaPlugin(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_mediaWidget(nullptr)
|
||||
, m_model(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
const QString MediaPlugin::pluginName() const
|
||||
{
|
||||
return "media";
|
||||
}
|
||||
|
||||
const QString MediaPlugin::pluginDisplayName() const
|
||||
{
|
||||
return tr("media");
|
||||
}
|
||||
|
||||
void MediaPlugin::init(PluginProxyInterface *proxyInter)
|
||||
{
|
||||
if (m_proxyInter == proxyInter)
|
||||
return;
|
||||
|
||||
m_proxyInter = proxyInter;
|
||||
|
||||
m_model.reset(new MediaPlayerModel);
|
||||
m_mediaWidget.reset(new MediaWidget(m_model.data()));
|
||||
m_mediaWidget->setFixedHeight(60);
|
||||
m_mediaWidget->setVisible(m_model->isActived());
|
||||
|
||||
if (m_model->isActived())
|
||||
m_proxyInter->itemAdded(this, pluginName());
|
||||
|
||||
connect(m_model.data(), &MediaPlayerModel::startStop, this, [ this ](bool visible) {
|
||||
if (visible)
|
||||
m_proxyInter->itemAdded(this, pluginName());
|
||||
else
|
||||
m_proxyInter->itemRemoved(this, pluginName());
|
||||
});
|
||||
}
|
||||
|
||||
QWidget *MediaPlugin::itemWidget(const QString &itemKey)
|
||||
{
|
||||
if (itemKey == QUICK_ITEM_KEY)
|
||||
return m_mediaWidget.data();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QWidget *MediaPlugin::itemTipsWidget(const QString &itemKey)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QWidget *MediaPlugin::itemPopupApplet(const QString &itemKey)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PluginFlags MediaPlugin::flags() const
|
||||
{
|
||||
return PluginFlag::Type_Common | PluginFlag::Quick_Full;
|
||||
}
|
57
plugins/media/mediaplugin.h
Normal file
57
plugins/media/mediaplugin.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: donghualin <donghualin@uniontech.com>
|
||||
*
|
||||
* Maintainer: donghualin <donghualin@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef MEDIAPLUGIN_H
|
||||
#define MEDIAPLUGIN_H
|
||||
|
||||
#include "pluginsiteminterface.h"
|
||||
|
||||
namespace Dock{
|
||||
class TipsWidget;
|
||||
}
|
||||
class MediaWidget;
|
||||
class MediaPlayerModel;
|
||||
|
||||
class MediaPlugin : public QObject, PluginsItemInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(PluginsItemInterface)
|
||||
Q_PLUGIN_METADATA(IID "com.deepin.dock.PluginsItemInterface" FILE "media.json")
|
||||
|
||||
public:
|
||||
explicit MediaPlugin(QObject *parent = nullptr);
|
||||
|
||||
const QString pluginName() const override;
|
||||
const QString pluginDisplayName() const override;
|
||||
void init(PluginProxyInterface *proxyInter) override;
|
||||
|
||||
QWidget *itemWidget(const QString &itemKey) override;
|
||||
QWidget *itemTipsWidget(const QString &itemKey) override;
|
||||
QWidget *itemPopupApplet(const QString &itemKey) override;
|
||||
|
||||
PluginFlags flags() const override;
|
||||
|
||||
private:
|
||||
QScopedPointer<MediaWidget> m_mediaWidget;
|
||||
QScopedPointer<MediaPlayerModel> m_model;
|
||||
};
|
||||
|
||||
#endif // DATETIMEPLUGIN_H
|
203
plugins/media/mediawidget.cpp
Normal file
203
plugins/media/mediawidget.cpp
Normal file
@ -0,0 +1,203 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: donghualin <donghualin@uniontech.com>
|
||||
*
|
||||
* Maintainer: donghualin <donghualin@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "mediawidget.h"
|
||||
|
||||
#include <DFontSizeManager>
|
||||
|
||||
#include <QLabel>
|
||||
#include <QHBoxLayout>
|
||||
#include <QVBoxLayout>
|
||||
#include <QEvent>
|
||||
#include <QPainter>
|
||||
#include <QDebug>
|
||||
#include <QPainterPath>
|
||||
|
||||
DWIDGET_USE_NAMESPACE
|
||||
|
||||
#define PAUSEHEIGHT 21
|
||||
#define PLAYHEIGHT 18
|
||||
|
||||
MediaWidget::MediaWidget(MediaPlayerModel *model, QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, m_model(model)
|
||||
, m_musicIcon(new QLabel(this))
|
||||
, m_musicName(new QLabel(this))
|
||||
, m_musicSinger(new QLabel(this))
|
||||
, m_pausePlayButton(new MusicButton(this))
|
||||
, m_nextButton(new MusicButton(this))
|
||||
{
|
||||
initUi();
|
||||
initConnection();
|
||||
}
|
||||
|
||||
MediaWidget::~MediaWidget()
|
||||
{
|
||||
}
|
||||
|
||||
void MediaWidget::statusChanged(const MediaPlayerModel::PlayStatus &newStatus)
|
||||
{
|
||||
switch (newStatus) {
|
||||
case MediaPlayerModel::PlayStatus::Play: {
|
||||
m_pausePlayButton->setButtonType(MusicButton::ButtonType::Pause);
|
||||
break;
|
||||
}
|
||||
case MediaPlayerModel::PlayStatus::Stop:
|
||||
case MediaPlayerModel::PlayStatus::Pause: {
|
||||
m_pausePlayButton->setButtonType(MusicButton::ButtonType::Playing);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
void MediaWidget::onPlayClicked()
|
||||
{
|
||||
// 设置当前的播放状态
|
||||
if (m_model->status() == MediaPlayerModel::PlayStatus::Play)
|
||||
m_model->setStatus(MediaPlayerModel::PlayStatus::Pause);
|
||||
else
|
||||
m_model->setStatus(MediaPlayerModel::PlayStatus::Play);
|
||||
}
|
||||
|
||||
void MediaWidget::onNext()
|
||||
{
|
||||
// 播放下一曲
|
||||
m_model->playNext();
|
||||
}
|
||||
|
||||
void MediaWidget::initUi()
|
||||
{
|
||||
m_pausePlayButton->setFixedWidth(20);
|
||||
m_nextButton->setFixedWidth(20);
|
||||
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout(this);
|
||||
mainLayout->setContentsMargins(20, 0, 20, 0);
|
||||
mainLayout->addWidget(m_musicIcon);
|
||||
|
||||
QWidget *infoWidget = new QWidget(this);
|
||||
QVBoxLayout *infoLayout = new QVBoxLayout(infoWidget);
|
||||
infoLayout->addWidget(m_musicName);
|
||||
infoLayout->addWidget(m_musicSinger);
|
||||
mainLayout->addWidget(infoWidget);
|
||||
mainLayout->addStretch();
|
||||
mainLayout->addWidget(m_pausePlayButton);
|
||||
mainLayout->addSpacing(25);
|
||||
mainLayout->addWidget(m_nextButton);
|
||||
|
||||
m_musicIcon->setFixedSize(32, 32);
|
||||
m_musicName->setFont(DFontSizeManager::instance()->t8());
|
||||
m_musicSinger->setFont(DFontSizeManager::instance()->t10());
|
||||
}
|
||||
|
||||
void MediaWidget::initConnection()
|
||||
{
|
||||
connect(m_model, &MediaPlayerModel::startStop, this, [ this ](bool startOrStop) {
|
||||
m_nextButton->setEnabled(m_model->canGoNext());
|
||||
onUpdateMediaInfo();
|
||||
statusChanged(m_model->status());
|
||||
});
|
||||
connect(m_model, &MediaPlayerModel::metadataChanged, this, &MediaWidget::onUpdateMediaInfo);
|
||||
connect(m_model, &MediaPlayerModel::statusChanged, this, &MediaWidget::statusChanged);
|
||||
connect(m_pausePlayButton, &MusicButton::clicked, this, &MediaWidget::onPlayClicked);
|
||||
connect(m_nextButton, &MusicButton::clicked, this, &MediaWidget::onNext);
|
||||
|
||||
m_pausePlayButton->setButtonType(m_model->status() == MediaPlayerModel::PlayStatus::Play ?
|
||||
MusicButton::ButtonType::Pause : MusicButton::ButtonType::Playing);
|
||||
m_nextButton->setButtonType(MusicButton::ButtonType::Next);
|
||||
}
|
||||
|
||||
void MediaWidget::onUpdateMediaInfo()
|
||||
{
|
||||
m_musicName->setText(m_model->name());
|
||||
QString file = m_model->iconUrl();
|
||||
if (file.startsWith("file:///"))
|
||||
file.replace("file:///", "/");
|
||||
m_musicIcon->setPixmap(QPixmap(file).scaled(m_musicIcon->size()));
|
||||
m_musicSinger->setText(m_model->artist());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 音乐播放的相关按钮
|
||||
* @param parent
|
||||
*/
|
||||
|
||||
MusicButton::MusicButton(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
installEventFilter(this);
|
||||
}
|
||||
|
||||
MusicButton::~MusicButton()
|
||||
{
|
||||
}
|
||||
|
||||
int MusicButton::getIconHeight() const
|
||||
{
|
||||
switch (m_buttonType) {
|
||||
case ButtonType::Pause:
|
||||
return PAUSEHEIGHT;
|
||||
case ButtonType::Next:
|
||||
case ButtonType::Playing:
|
||||
return PLAYHEIGHT;
|
||||
}
|
||||
|
||||
return PLAYHEIGHT;
|
||||
}
|
||||
|
||||
void MusicButton::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
|
||||
#define ICOMMARGIN 6
|
||||
#define ICONSPACE 2
|
||||
|
||||
int ctrlHeight = getIconHeight();
|
||||
|
||||
int width = this->width();
|
||||
int height = this->height();
|
||||
int startX = 2;
|
||||
int startY = (height - ctrlHeight) / 2;
|
||||
QPainter painter(this);
|
||||
painter.save();
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.setPen(Qt::black);
|
||||
painter.setBrush(Qt::black);
|
||||
if (m_buttonType == ButtonType::Pause) {
|
||||
painter.drawRect(QRect(startX, startY, ICOMMARGIN, ctrlHeight));
|
||||
painter.drawRect(QRect(width - ICOMMARGIN - ICONSPACE, startY, ICOMMARGIN, ctrlHeight));
|
||||
} else {
|
||||
QPainterPath trianglePath;
|
||||
trianglePath.moveTo(startX, startY);
|
||||
trianglePath.lineTo(width - ICOMMARGIN, height / 2);
|
||||
trianglePath.lineTo(startX, startY + ctrlHeight);
|
||||
trianglePath.lineTo(startX, startY);
|
||||
painter.drawPath(trianglePath);
|
||||
if (m_buttonType == ButtonType::Next)
|
||||
painter.drawRect(width - ICOMMARGIN, startY, 2, ctrlHeight);
|
||||
}
|
||||
painter.restore();
|
||||
}
|
||||
|
||||
void MusicButton::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
Q_EMIT clicked();
|
||||
}
|
92
plugins/media/mediawidget.h
Normal file
92
plugins/media/mediawidget.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: donghualin <donghualin@uniontech.com>
|
||||
*
|
||||
* Maintainer: donghualin <donghualin@uniontech.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef MEDIAWIDGET_H
|
||||
#define MEDIAWIDGET_H
|
||||
|
||||
#include "mediaplayermodel.h"
|
||||
|
||||
#include <DBlurEffectWidget>
|
||||
|
||||
class QLabel;
|
||||
class MusicButton;
|
||||
class MediaPlayerModel;
|
||||
|
||||
DWIDGET_USE_NAMESPACE
|
||||
|
||||
class MediaWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MediaWidget(MediaPlayerModel *model, QWidget *parent = nullptr);
|
||||
~MediaWidget() override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void statusChanged(const MediaPlayerModel::PlayStatus &newStatus);
|
||||
void onPlayClicked();
|
||||
void onNext();
|
||||
void onUpdateMediaInfo();
|
||||
|
||||
private:
|
||||
void initUi();
|
||||
void initConnection();
|
||||
|
||||
private:
|
||||
MediaPlayerModel *m_model;
|
||||
QLabel *m_musicIcon;
|
||||
QLabel *m_musicName;
|
||||
QLabel *m_musicSinger;
|
||||
MusicButton *m_pausePlayButton;
|
||||
MusicButton *m_nextButton;
|
||||
};
|
||||
|
||||
// 音乐播放按钮
|
||||
class MusicButton : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_SIGNALS:
|
||||
void clicked();
|
||||
|
||||
public:
|
||||
enum ButtonType { Playing = 0, Pause, Next };
|
||||
|
||||
public:
|
||||
MusicButton(QWidget *parent = Q_NULLPTR);
|
||||
~MusicButton() override;
|
||||
|
||||
inline void setButtonType(const ButtonType &bt) {
|
||||
m_buttonType = bt;
|
||||
update();
|
||||
}
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
|
||||
private:
|
||||
int getIconHeight() const;
|
||||
|
||||
private:
|
||||
ButtonType m_buttonType;
|
||||
};
|
||||
|
||||
#endif // MEDIAWIDGER_H
|
Loading…
x
Reference in New Issue
Block a user