From 84fe750a3a55248571d2b204322b725116d81d51 Mon Sep 17 00:00:00 2001 From: trialuser02 Date: Sat, 23 Feb 2019 20:12:20 +0000 Subject: mpris: changed source structure git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@8727 90c681e8-e032-0410-971d-27865f9a5e38 --- src/plugins/General/mpris/CMakeLists.txt | 4 +- src/plugins/General/mpris/mpris.cpp | 4 +- src/plugins/General/mpris/mpris.pro | 8 +- src/plugins/General/mpris/mpris2/player2object.cpp | 393 --------------------- src/plugins/General/mpris/mpris2/player2object.h | 119 ------- src/plugins/General/mpris/mpris2/root2object.cpp | 91 ----- src/plugins/General/mpris/mpris2/root2object.h | 58 --- src/plugins/General/mpris/player2object.cpp | 393 +++++++++++++++++++++ src/plugins/General/mpris/player2object.h | 119 +++++++ src/plugins/General/mpris/root2object.cpp | 91 +++++ src/plugins/General/mpris/root2object.h | 58 +++ 11 files changed, 669 insertions(+), 669 deletions(-) delete mode 100644 src/plugins/General/mpris/mpris2/player2object.cpp delete mode 100644 src/plugins/General/mpris/mpris2/player2object.h delete mode 100644 src/plugins/General/mpris/mpris2/root2object.cpp delete mode 100644 src/plugins/General/mpris/mpris2/root2object.h create mode 100644 src/plugins/General/mpris/player2object.cpp create mode 100644 src/plugins/General/mpris/player2object.h create mode 100644 src/plugins/General/mpris/root2object.cpp create mode 100644 src/plugins/General/mpris/root2object.h (limited to 'src/plugins/General/mpris') diff --git a/src/plugins/General/mpris/CMakeLists.txt b/src/plugins/General/mpris/CMakeLists.txt index e18c46b53..669649d22 100644 --- a/src/plugins/General/mpris/CMakeLists.txt +++ b/src/plugins/General/mpris/CMakeLists.txt @@ -10,8 +10,8 @@ link_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../qmmp) SET(libmpris_SRCS mpris.cpp mprisfactory.cpp - mpris2/root2object.cpp - mpris2/player2object.cpp + root2object.cpp + player2object.cpp ) SET(libmpris_RCCS translations/translations.qrc) diff --git a/src/plugins/General/mpris/mpris.cpp b/src/plugins/General/mpris/mpris.cpp index 4cf5df042..d373f3bc4 100644 --- a/src/plugins/General/mpris/mpris.cpp +++ b/src/plugins/General/mpris/mpris.cpp @@ -19,8 +19,8 @@ ***************************************************************************/ #include -#include "mpris2/root2object.h" -#include "mpris2/player2object.h" +#include "root2object.h" +#include "player2object.h" #include "mpris.h" MPRIS::MPRIS(QObject *parent) : QObject(parent) diff --git a/src/plugins/General/mpris/mpris.pro b/src/plugins/General/mpris/mpris.pro index b13250c34..7d7cdd4b6 100644 --- a/src/plugins/General/mpris/mpris.pro +++ b/src/plugins/General/mpris/mpris.pro @@ -6,13 +6,13 @@ QT += dbus HEADERS += mprisfactory.h \ mpris.h \ - mpris2/root2object.h \ - mpris2/player2object.h + root2object.h \ + player2object.h SOURCES += mprisfactory.cpp \ mpris.cpp \ - mpris2/root2object.cpp \ - mpris2/player2object.cpp + root2object.cpp \ + player2object.cpp RESOURCES = translations/translations.qrc diff --git a/src/plugins/General/mpris/mpris2/player2object.cpp b/src/plugins/General/mpris/mpris2/player2object.cpp deleted file mode 100644 index 7773d86ae..000000000 --- a/src/plugins/General/mpris/mpris2/player2object.cpp +++ /dev/null @@ -1,393 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2010-2019 by Ilya Kotov * - * forkotov02@ya.ru * - * * - * 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 2 of the License, 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, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - ***************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "player2object.h" - -Player2Object::Player2Object(QObject *parent) : QDBusAbstractAdaptor(parent) -{ - m_prev_track = nullptr; - m_previous_pos = 0; - m_core = SoundCore::instance(); - m_player = MediaPlayer::instance(); - m_pl_manager = m_player->playListManager(); - m_ui_settings = QmmpUiSettings::instance(); - connect(m_core, SIGNAL(trackInfoChanged()), SLOT(updateId())); - connect(m_core, SIGNAL(trackInfoChanged()), SLOT(emitPropertiesChanged())); - connect(m_core, SIGNAL(stateChanged (Qmmp::State)), SLOT(checkState(Qmmp::State))); - connect(m_core, SIGNAL(stateChanged (Qmmp::State)), SLOT(emitPropertiesChanged())); - connect(m_core, SIGNAL(volumeChanged(int,int)), SLOT(emitPropertiesChanged())); - connect(m_core, SIGNAL(elapsedChanged(qint64)), SLOT(checkSeeking(qint64))); - connect(m_ui_settings, SIGNAL(repeatableListChanged(bool)), SLOT(emitPropertiesChanged())); - connect(m_ui_settings, SIGNAL(repeatableTrackChanged(bool)), SLOT(emitPropertiesChanged())); - connect(m_ui_settings, SIGNAL(shuffleChanged(bool)), SLOT(emitPropertiesChanged())); - connect(m_pl_manager, SIGNAL(currentPlayListChanged(PlayListModel*,PlayListModel*)), - SLOT(setModel(PlayListModel*,PlayListModel*))); - setModel(m_pl_manager->currentPlayList(), nullptr); - updateId(); - syncProperties(); -} - -Player2Object::~Player2Object() -{} - -bool Player2Object::canControl() const -{ - return true; -} - -bool Player2Object::canGoNext() const -{ - return m_pl_manager->currentPlayList()->nextTrack() != nullptr; -} - -bool Player2Object::canGoPrevious() const -{ - return m_pl_manager->currentPlayList()->currentIndex() > 0; -} - -bool Player2Object::canPause() const -{ - return (m_core->state() == Qmmp::Paused || m_core->state() == Qmmp::Playing); -} -bool Player2Object::canPlay() const -{ - return m_pl_manager->currentPlayList()->count() != 0; -} - -bool Player2Object::canSeek() const -{ - return m_core->duration() > 0; -} - -QString Player2Object::loopStatus() const -{ - if(m_ui_settings->isRepeatableTrack()) - return "Track"; - else if(m_ui_settings->isRepeatableList()) - return "Playlist"; - else - return "None"; -} - -void Player2Object::setLoopStatus(const QString &value) -{ - if(value == "Track") - { - m_ui_settings->setRepeatableList(false); - m_ui_settings->setRepeatableTrack(true); - } - else if(value == "Playlist") - { - m_ui_settings->setRepeatableList(true); - m_ui_settings->setRepeatableTrack(false); - } - else - { - m_ui_settings->setRepeatableList(false); - m_ui_settings->setRepeatableTrack(false); - } -} - -double Player2Object::maximumRate() const -{ - return 1.0; -} - -QVariantMap Player2Object::metadata() const -{ - PlayListTrack *track = m_pl_manager->currentPlayList()->currentTrack(); - if(!track || m_core->path().isEmpty()) - return QVariantMap(); - QVariantMap map; - TrackInfo info = m_core->trackInfo(); - map["mpris:length"] = qMax(m_core->duration() * 1000 , qint64(0)); - if(!MetaDataManager::instance()->getCoverPath(info.path()).isEmpty()) - { - map["mpris:artUrl"] = QUrl::fromLocalFile( - MetaDataManager::instance()->getCoverPath(info.path())).toString(); - } - if(!info.value(Qmmp::ALBUM).isEmpty()) - map["xesam:album"] = info.value(Qmmp::ALBUM); - if(!info.value(Qmmp::ARTIST).isEmpty()) - map["xesam:artist"] = QStringList() << info.value(Qmmp::ARTIST); - if(!info.value(Qmmp::ALBUMARTIST).isEmpty()) - map["xesam:albumArtist"] = QStringList() << info.value(Qmmp::ALBUMARTIST); - if(!info.value(Qmmp::COMMENT).isEmpty()) - map["xesam:comment"] = QStringList() << info.value(Qmmp::COMMENT); - if(!info.value(Qmmp::COMPOSER).isEmpty()) - map["xesam:composer"] = QStringList() << info.value(Qmmp::COMPOSER); - if(!info.value(Qmmp::DISCNUMBER).isEmpty()) - map["xesam:discNumber"] = info.value(Qmmp::DISCNUMBER).toInt(); - if(!info.value(Qmmp::GENRE).isEmpty()) - map["xesam:genre"] = QStringList() << info.value(Qmmp::GENRE); - if(!info.value(Qmmp::TITLE).isEmpty()) - map["xesam:title"] = info.value(Qmmp::TITLE); - if(!info.value(Qmmp::TRACK).isEmpty()) - map["xesam:trackNumber"] = info.value(Qmmp::TRACK).toInt(); - if(!info.value(Qmmp::YEAR).isEmpty()) - map["xesam:contentCreated"] = info.value(Qmmp::YEAR); - map["mpris:trackid"] = QVariant::fromValue(m_trackID); - if(info.path().startsWith("/")) - map["xesam:url"] = QUrl::fromLocalFile(info.path()).toString(); - else - map["xesam:url"] = info.path(); - return map; -} - -double Player2Object::minimumRate() const -{ - return 1.0; -} - -QString Player2Object::playbackStatus() const -{ - if(m_core->state() == Qmmp::Playing) - return "Playing"; - else if (m_core->state() == Qmmp::Paused) - return "Paused"; - return "Stopped"; -} - -qlonglong Player2Object::position() const -{ - return qMax(m_core->elapsed() * 1000, qint64(0)); -} - -double Player2Object::rate() const -{ - return 1.0; -} - -void Player2Object::setRate(double value) -{ - Q_UNUSED(value) -} - -bool Player2Object::shuffle() const -{ - return m_ui_settings->isShuffle(); -} - -void Player2Object::setShuffle(bool value) -{ - m_ui_settings->setShuffle(value); -} - -double Player2Object::volume() const -{ - return qMax(m_core->leftVolume(), m_core->rightVolume())/100.0; -} - -void Player2Object::Player2Object::setVolume(double value) -{ - value = qBound(0.0, value ,1.0); - int balance = (volume() > 0) ? (m_core->rightVolume() - m_core->leftVolume())/volume() : 0; - m_core->setVolume(value*100 - qMax(balance,0)*value, - value*100 + qMin(balance,0)*value); -} - -void Player2Object::Next() -{ - m_player->next(); -} - -void Player2Object::OpenUri(const QString &in0) -{ - QString path = in0; - if(in0.startsWith("file://")) - { - path = QUrl(in0).toLocalFile (); - if(!QFile::exists(path)) - return; //error - } - if(!m_pl_manager->currentPlayList()->isLoaderRunning()) - { - m_pl_manager->selectPlayList(m_pl_manager->currentPlayList()); - connect(m_pl_manager->currentPlayList(), SIGNAL(trackAdded(PlayListTrack*)), - SLOT(playTrack(PlayListTrack*))); - connect(m_pl_manager->currentPlayList(), SIGNAL(loaderFinished()), this, SLOT(disconnectPl())); - } - m_pl_manager->currentPlayList()->add(path); -} - -void Player2Object::Pause() -{ - m_core->pause(); -} - -void Player2Object::Play() -{ - m_player->play(); -} - -void Player2Object::PlayPause() -{ - if(m_core->state() == Qmmp::Stopped) - m_player->play(); - else if(m_core->state() == Qmmp::Paused || m_core->state() == Qmmp::Playing) - m_core->pause(); -} - -void Player2Object::Previous() -{ - m_player->previous(); -} - -void Player2Object::Seek(qlonglong Offset) -{ - m_core->seek(qMax(qint64(0), m_core->elapsed() + Offset/1000)); -} -void Player2Object::SetPosition(const QDBusObjectPath &TrackId, qlonglong Position) -{ - if(m_trackID == TrackId) - m_core->seek(Position/1000); - else - qWarning("Player2Object: SetPosition() called with a invalid trackId"); -} - -void Player2Object::Stop() -{ - m_core->stop(); -} - -void Player2Object::emitPropertiesChanged() -{ - QList changedProps; - if(m_props["CanGoNext"] != canGoNext()) - changedProps << "CanGoNext"; - if(m_props["CanGoPrevious"] != canGoPrevious()) - changedProps << "CanGoPrevious"; - if(m_props["CanPause"] != canPause()) - changedProps << "CanPause"; - if(m_props["CanPlay"] != canPlay()) - changedProps << "CanPlay"; - if(m_props["CanSeek"] != canSeek()) - changedProps << "CanSeek"; - if(m_props["LoopStatus"] != loopStatus()) - changedProps << "LoopStatus"; - if(m_props["MaximumRate"] != maximumRate()) - changedProps << "MaximumRate"; - if(m_props["MinimumRate"] != minimumRate()) - changedProps << "MinimumRate"; - if(m_props["PlaybackStatus"] != playbackStatus()) - changedProps << "PlaybackStatus"; - if(m_props["Rate"] != rate()) - changedProps << "Rate"; - if(m_props["Shuffle"] != shuffle()) - changedProps << "Shuffle"; - if(m_props["Volume"] != volume()) - changedProps << "Volume"; - if(m_props["Metadata"] != metadata()) - changedProps << "Metadata"; - - if(changedProps.isEmpty()) - return; - - syncProperties(); - - QVariantMap map; - foreach(QByteArray name, changedProps) - map.insert(name, m_props.value(name)); - - QDBusMessage msg = QDBusMessage::createSignal("/org/mpris/MediaPlayer2", - "org.freedesktop.DBus.Properties", "PropertiesChanged"); - msg << "org.mpris.MediaPlayer2.Player"; - msg << map; - msg << QStringList(); - QDBusConnection::sessionBus().send(msg); -} - -void Player2Object::updateId() -{ - if(m_prev_track != m_pl_manager->currentPlayList()->currentTrack()) - { - m_trackID = QDBusObjectPath(QString("%1/Track/%2").arg("/org/qmmp/MediaPlayer2").arg(qrand())); - m_prev_track = m_pl_manager->currentPlayList()->currentTrack(); - } -} - -void Player2Object::checkState(Qmmp::State state) -{ - if(state == Qmmp::Playing) - { - updateId(); - m_previous_pos = 0; - } -} - -void Player2Object::checkSeeking(qint64 elapsed) -{ - if(abs(elapsed - m_previous_pos) > 2000) - { - emit Seeked(elapsed * 1000); - } - m_previous_pos = elapsed; -} - -void Player2Object::playTrack(PlayListTrack *item) -{ - m_pl_manager->selectPlayList((PlayListModel*)sender()); - m_pl_manager->activatePlayList((PlayListModel*)sender()); - disconnect(sender(), SIGNAL(trackAdded(PlayListTrack*)), this, SLOT(playTrack(PlayListTrack*))); - if(!m_pl_manager->currentPlayList()->setCurrent(item)) - return; - m_core->stop(); - m_player->play(); -} - -void Player2Object::disconnectPl() -{ - disconnect(sender(), SIGNAL(trackAdded(PlayListTrack*)), - this, SLOT(playTrack(PlayListTrack*))); -} - -void Player2Object::setModel(PlayListModel *selected, PlayListModel *previous) -{ - if(previous) - disconnect(previous, nullptr, this, nullptr); //disconnect previous model - connect(selected, SIGNAL(listChanged(int)), SLOT(emitPropertiesChanged())); -} - -void Player2Object::syncProperties() -{ - m_props["CanGoNext"] = canGoNext(); - m_props["CanGoPrevious"] = canGoPrevious(); - m_props["CanPause"] = canPause(); - m_props["CanPlay"] = canPlay(); - m_props["CanSeek"] = canSeek(); - m_props["LoopStatus"] = loopStatus(); - m_props["MaximumRate"] = maximumRate(); - m_props["MinimumRate"] = minimumRate(); - m_props["PlaybackStatus"] = playbackStatus(); - m_props["Rate"] = rate(); - m_props["Shuffle"] = shuffle(); - m_props["Volume"] = volume(); - m_props["Metadata"] = metadata(); -} diff --git a/src/plugins/General/mpris/mpris2/player2object.h b/src/plugins/General/mpris/mpris2/player2object.h deleted file mode 100644 index af69844a4..000000000 --- a/src/plugins/General/mpris/mpris2/player2object.h +++ /dev/null @@ -1,119 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2010-2015 by Ilya Kotov * - * forkotov02@ya.ru * - * * - * 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 2 of the License, 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, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - ***************************************************************************/ -#ifndef PLAYER2OBJECT_H -#define PLAYER2OBJECT_H - -#include -#include -#include -#include -#include -#include - -class SoundCore; -class MediaPlayer; -class PlayListManager; -class PlayListTrack; -class PlayListModel; -class QmmpUiSettings; - -/** - @author Ilya Kotov -*/ -class Player2Object : public QDBusAbstractAdaptor -{ -Q_OBJECT -Q_CLASSINFO("D-Bus Interface", "org.mpris.MediaPlayer2.Player") -Q_PROPERTY(bool CanControl READ canControl) -Q_PROPERTY(bool CanGoNext READ canGoNext) -Q_PROPERTY(bool CanGoPrevious READ canGoPrevious) -Q_PROPERTY(bool CanPause READ canPause) -Q_PROPERTY(bool CanPlay READ canPlay) -Q_PROPERTY(bool CanSeek READ canSeek) -Q_PROPERTY(QString LoopStatus READ loopStatus WRITE setLoopStatus) -Q_PROPERTY(double MaximumRate READ maximumRate) -Q_PROPERTY(QVariantMap Metadata READ metadata) -Q_PROPERTY(double MinimumRate READ minimumRate) -Q_PROPERTY(QString PlaybackStatus READ playbackStatus) -Q_PROPERTY(qlonglong Position READ position) -Q_PROPERTY(double Rate READ rate WRITE setRate) -Q_PROPERTY(bool Shuffle READ shuffle WRITE setShuffle) -Q_PROPERTY(double Volume READ volume WRITE setVolume) - -public: - Player2Object(QObject *parent = nullptr); - virtual ~Player2Object(); - bool canControl() const; - bool canGoNext() const; - bool canGoPrevious() const; - bool canPause() const; - bool canPlay() const; - bool canSeek() const; - QString loopStatus() const; - void setLoopStatus(const QString &value); - double maximumRate() const; - QVariantMap metadata() const; - double minimumRate() const; - QString playbackStatus() const; - qlonglong position() const; - double rate() const; - void setRate(double value); - bool shuffle() const; - void setShuffle(bool value); - double volume() const; - void setVolume(double value); - -public slots: - void Next(); - void OpenUri(const QString &in0); - void Pause(); - void Play(); - void PlayPause(); - void Previous(); - void Seek(qlonglong Offset); - void SetPosition(const QDBusObjectPath &TrackId, qlonglong Position); - void Stop(); -signals: - void Seeked(qlonglong Position); - -private slots: - void emitPropertiesChanged(); - void updateId(); - void checkState(Qmmp::State state); - void checkSeeking(qint64 elapsed); - void playTrack(PlayListTrack *item); - void disconnectPl(); - void setModel(PlayListModel *selected, PlayListModel *previous); - - -private: - void syncProperties(); - SoundCore *m_core; - MediaPlayer *m_player; - PlayListManager *m_pl_manager; - QmmpUiSettings *m_ui_settings; - QMap m_props; - QDBusObjectPath m_trackID; - PlayListTrack *m_prev_track; - qint64 m_previous_pos; - -}; - -#endif diff --git a/src/plugins/General/mpris/mpris2/root2object.cpp b/src/plugins/General/mpris/mpris2/root2object.cpp deleted file mode 100644 index a7e9bdd50..000000000 --- a/src/plugins/General/mpris/mpris2/root2object.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2010-2019 by Ilya Kotov * - * forkotov02@ya.ru * - * * - * 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 2 of the License, 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, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - ***************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "root2object.h" - -Root2Object::Root2Object(QObject *parent) : QDBusAbstractAdaptor(parent) -{} - - -Root2Object::~Root2Object() -{} - -bool Root2Object::canQuit() const -{ - return true; -} - -bool Root2Object::canRaise() const -{ - return true; -} - -QString Root2Object::desktopEntry() const -{ - return "qmmp"; -} - -bool Root2Object::hasTrackList() const -{ - return false; -} -QString Root2Object::identity() const -{ - return "Qmmp"; -} - -QStringList Root2Object::supportedMimeTypes() const -{ - QStringList mimeTypes; - foreach(DecoderFactory *factory, Decoder::enabledFactories()) - mimeTypes << factory->properties().contentTypes; - foreach(EngineFactory *factory, AbstractEngine::enabledFactories()) - mimeTypes << factory->properties().contentTypes; - mimeTypes.removeDuplicates(); - return mimeTypes; -} - -QStringList Root2Object::supportedUriSchemes() const -{ - QStringList protocols = MetaDataManager::instance()->protocols(); - if(!protocols.contains("file")) //append file if needed - protocols.append("file"); - return protocols; -} - -void Root2Object::Quit() -{ - UiHelper::instance()->exit(); -} - -void Root2Object::Raise() -{ - UiHelper::instance()->showMainWindow(); -} diff --git a/src/plugins/General/mpris/mpris2/root2object.h b/src/plugins/General/mpris/mpris2/root2object.h deleted file mode 100644 index 762e04655..000000000 --- a/src/plugins/General/mpris/mpris2/root2object.h +++ /dev/null @@ -1,58 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2010-2012 by Ilya Kotov * - * forkotov02@ya.ru * - * * - * 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 2 of the License, 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, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - ***************************************************************************/ -#ifndef ROOT2OBJECT_H -#define ROOT2OBJECT_H - -#include -#include - -/** - @author Ilya Kotov -*/ -class Root2Object : public QDBusAbstractAdaptor -{ -Q_OBJECT -Q_CLASSINFO("D-Bus Interface", "org.mpris.MediaPlayer2") -Q_PROPERTY(bool CanQuit READ canQuit) -Q_PROPERTY(bool CanRaise READ canRaise) -Q_PROPERTY(QString DesktopEntry READ desktopEntry) -Q_PROPERTY(bool HasTrackList READ hasTrackList) -Q_PROPERTY(QString Identity READ identity) -Q_PROPERTY(QStringList SupportedMimeTypes READ supportedMimeTypes) -Q_PROPERTY(QStringList SupportedUriSchemes READ supportedUriSchemes) - -public: - Root2Object(QObject *parent = nullptr); - virtual ~Root2Object(); - - bool canQuit() const; - bool canRaise() const; - QString desktopEntry() const; - bool hasTrackList() const; - QString identity() const; - QStringList supportedMimeTypes() const; - QStringList supportedUriSchemes() const; - -public slots: - void Quit(); - void Raise(); -}; - -#endif diff --git a/src/plugins/General/mpris/player2object.cpp b/src/plugins/General/mpris/player2object.cpp new file mode 100644 index 000000000..7773d86ae --- /dev/null +++ b/src/plugins/General/mpris/player2object.cpp @@ -0,0 +1,393 @@ +/*************************************************************************** + * Copyright (C) 2010-2019 by Ilya Kotov * + * forkotov02@ya.ru * + * * + * 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 2 of the License, 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, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "player2object.h" + +Player2Object::Player2Object(QObject *parent) : QDBusAbstractAdaptor(parent) +{ + m_prev_track = nullptr; + m_previous_pos = 0; + m_core = SoundCore::instance(); + m_player = MediaPlayer::instance(); + m_pl_manager = m_player->playListManager(); + m_ui_settings = QmmpUiSettings::instance(); + connect(m_core, SIGNAL(trackInfoChanged()), SLOT(updateId())); + connect(m_core, SIGNAL(trackInfoChanged()), SLOT(emitPropertiesChanged())); + connect(m_core, SIGNAL(stateChanged (Qmmp::State)), SLOT(checkState(Qmmp::State))); + connect(m_core, SIGNAL(stateChanged (Qmmp::State)), SLOT(emitPropertiesChanged())); + connect(m_core, SIGNAL(volumeChanged(int,int)), SLOT(emitPropertiesChanged())); + connect(m_core, SIGNAL(elapsedChanged(qint64)), SLOT(checkSeeking(qint64))); + connect(m_ui_settings, SIGNAL(repeatableListChanged(bool)), SLOT(emitPropertiesChanged())); + connect(m_ui_settings, SIGNAL(repeatableTrackChanged(bool)), SLOT(emitPropertiesChanged())); + connect(m_ui_settings, SIGNAL(shuffleChanged(bool)), SLOT(emitPropertiesChanged())); + connect(m_pl_manager, SIGNAL(currentPlayListChanged(PlayListModel*,PlayListModel*)), + SLOT(setModel(PlayListModel*,PlayListModel*))); + setModel(m_pl_manager->currentPlayList(), nullptr); + updateId(); + syncProperties(); +} + +Player2Object::~Player2Object() +{} + +bool Player2Object::canControl() const +{ + return true; +} + +bool Player2Object::canGoNext() const +{ + return m_pl_manager->currentPlayList()->nextTrack() != nullptr; +} + +bool Player2Object::canGoPrevious() const +{ + return m_pl_manager->currentPlayList()->currentIndex() > 0; +} + +bool Player2Object::canPause() const +{ + return (m_core->state() == Qmmp::Paused || m_core->state() == Qmmp::Playing); +} +bool Player2Object::canPlay() const +{ + return m_pl_manager->currentPlayList()->count() != 0; +} + +bool Player2Object::canSeek() const +{ + return m_core->duration() > 0; +} + +QString Player2Object::loopStatus() const +{ + if(m_ui_settings->isRepeatableTrack()) + return "Track"; + else if(m_ui_settings->isRepeatableList()) + return "Playlist"; + else + return "None"; +} + +void Player2Object::setLoopStatus(const QString &value) +{ + if(value == "Track") + { + m_ui_settings->setRepeatableList(false); + m_ui_settings->setRepeatableTrack(true); + } + else if(value == "Playlist") + { + m_ui_settings->setRepeatableList(true); + m_ui_settings->setRepeatableTrack(false); + } + else + { + m_ui_settings->setRepeatableList(false); + m_ui_settings->setRepeatableTrack(false); + } +} + +double Player2Object::maximumRate() const +{ + return 1.0; +} + +QVariantMap Player2Object::metadata() const +{ + PlayListTrack *track = m_pl_manager->currentPlayList()->currentTrack(); + if(!track || m_core->path().isEmpty()) + return QVariantMap(); + QVariantMap map; + TrackInfo info = m_core->trackInfo(); + map["mpris:length"] = qMax(m_core->duration() * 1000 , qint64(0)); + if(!MetaDataManager::instance()->getCoverPath(info.path()).isEmpty()) + { + map["mpris:artUrl"] = QUrl::fromLocalFile( + MetaDataManager::instance()->getCoverPath(info.path())).toString(); + } + if(!info.value(Qmmp::ALBUM).isEmpty()) + map["xesam:album"] = info.value(Qmmp::ALBUM); + if(!info.value(Qmmp::ARTIST).isEmpty()) + map["xesam:artist"] = QStringList() << info.value(Qmmp::ARTIST); + if(!info.value(Qmmp::ALBUMARTIST).isEmpty()) + map["xesam:albumArtist"] = QStringList() << info.value(Qmmp::ALBUMARTIST); + if(!info.value(Qmmp::COMMENT).isEmpty()) + map["xesam:comment"] = QStringList() << info.value(Qmmp::COMMENT); + if(!info.value(Qmmp::COMPOSER).isEmpty()) + map["xesam:composer"] = QStringList() << info.value(Qmmp::COMPOSER); + if(!info.value(Qmmp::DISCNUMBER).isEmpty()) + map["xesam:discNumber"] = info.value(Qmmp::DISCNUMBER).toInt(); + if(!info.value(Qmmp::GENRE).isEmpty()) + map["xesam:genre"] = QStringList() << info.value(Qmmp::GENRE); + if(!info.value(Qmmp::TITLE).isEmpty()) + map["xesam:title"] = info.value(Qmmp::TITLE); + if(!info.value(Qmmp::TRACK).isEmpty()) + map["xesam:trackNumber"] = info.value(Qmmp::TRACK).toInt(); + if(!info.value(Qmmp::YEAR).isEmpty()) + map["xesam:contentCreated"] = info.value(Qmmp::YEAR); + map["mpris:trackid"] = QVariant::fromValue(m_trackID); + if(info.path().startsWith("/")) + map["xesam:url"] = QUrl::fromLocalFile(info.path()).toString(); + else + map["xesam:url"] = info.path(); + return map; +} + +double Player2Object::minimumRate() const +{ + return 1.0; +} + +QString Player2Object::playbackStatus() const +{ + if(m_core->state() == Qmmp::Playing) + return "Playing"; + else if (m_core->state() == Qmmp::Paused) + return "Paused"; + return "Stopped"; +} + +qlonglong Player2Object::position() const +{ + return qMax(m_core->elapsed() * 1000, qint64(0)); +} + +double Player2Object::rate() const +{ + return 1.0; +} + +void Player2Object::setRate(double value) +{ + Q_UNUSED(value) +} + +bool Player2Object::shuffle() const +{ + return m_ui_settings->isShuffle(); +} + +void Player2Object::setShuffle(bool value) +{ + m_ui_settings->setShuffle(value); +} + +double Player2Object::volume() const +{ + return qMax(m_core->leftVolume(), m_core->rightVolume())/100.0; +} + +void Player2Object::Player2Object::setVolume(double value) +{ + value = qBound(0.0, value ,1.0); + int balance = (volume() > 0) ? (m_core->rightVolume() - m_core->leftVolume())/volume() : 0; + m_core->setVolume(value*100 - qMax(balance,0)*value, + value*100 + qMin(balance,0)*value); +} + +void Player2Object::Next() +{ + m_player->next(); +} + +void Player2Object::OpenUri(const QString &in0) +{ + QString path = in0; + if(in0.startsWith("file://")) + { + path = QUrl(in0).toLocalFile (); + if(!QFile::exists(path)) + return; //error + } + if(!m_pl_manager->currentPlayList()->isLoaderRunning()) + { + m_pl_manager->selectPlayList(m_pl_manager->currentPlayList()); + connect(m_pl_manager->currentPlayList(), SIGNAL(trackAdded(PlayListTrack*)), + SLOT(playTrack(PlayListTrack*))); + connect(m_pl_manager->currentPlayList(), SIGNAL(loaderFinished()), this, SLOT(disconnectPl())); + } + m_pl_manager->currentPlayList()->add(path); +} + +void Player2Object::Pause() +{ + m_core->pause(); +} + +void Player2Object::Play() +{ + m_player->play(); +} + +void Player2Object::PlayPause() +{ + if(m_core->state() == Qmmp::Stopped) + m_player->play(); + else if(m_core->state() == Qmmp::Paused || m_core->state() == Qmmp::Playing) + m_core->pause(); +} + +void Player2Object::Previous() +{ + m_player->previous(); +} + +void Player2Object::Seek(qlonglong Offset) +{ + m_core->seek(qMax(qint64(0), m_core->elapsed() + Offset/1000)); +} +void Player2Object::SetPosition(const QDBusObjectPath &TrackId, qlonglong Position) +{ + if(m_trackID == TrackId) + m_core->seek(Position/1000); + else + qWarning("Player2Object: SetPosition() called with a invalid trackId"); +} + +void Player2Object::Stop() +{ + m_core->stop(); +} + +void Player2Object::emitPropertiesChanged() +{ + QList changedProps; + if(m_props["CanGoNext"] != canGoNext()) + changedProps << "CanGoNext"; + if(m_props["CanGoPrevious"] != canGoPrevious()) + changedProps << "CanGoPrevious"; + if(m_props["CanPause"] != canPause()) + changedProps << "CanPause"; + if(m_props["CanPlay"] != canPlay()) + changedProps << "CanPlay"; + if(m_props["CanSeek"] != canSeek()) + changedProps << "CanSeek"; + if(m_props["LoopStatus"] != loopStatus()) + changedProps << "LoopStatus"; + if(m_props["MaximumRate"] != maximumRate()) + changedProps << "MaximumRate"; + if(m_props["MinimumRate"] != minimumRate()) + changedProps << "MinimumRate"; + if(m_props["PlaybackStatus"] != playbackStatus()) + changedProps << "PlaybackStatus"; + if(m_props["Rate"] != rate()) + changedProps << "Rate"; + if(m_props["Shuffle"] != shuffle()) + changedProps << "Shuffle"; + if(m_props["Volume"] != volume()) + changedProps << "Volume"; + if(m_props["Metadata"] != metadata()) + changedProps << "Metadata"; + + if(changedProps.isEmpty()) + return; + + syncProperties(); + + QVariantMap map; + foreach(QByteArray name, changedProps) + map.insert(name, m_props.value(name)); + + QDBusMessage msg = QDBusMessage::createSignal("/org/mpris/MediaPlayer2", + "org.freedesktop.DBus.Properties", "PropertiesChanged"); + msg << "org.mpris.MediaPlayer2.Player"; + msg << map; + msg << QStringList(); + QDBusConnection::sessionBus().send(msg); +} + +void Player2Object::updateId() +{ + if(m_prev_track != m_pl_manager->currentPlayList()->currentTrack()) + { + m_trackID = QDBusObjectPath(QString("%1/Track/%2").arg("/org/qmmp/MediaPlayer2").arg(qrand())); + m_prev_track = m_pl_manager->currentPlayList()->currentTrack(); + } +} + +void Player2Object::checkState(Qmmp::State state) +{ + if(state == Qmmp::Playing) + { + updateId(); + m_previous_pos = 0; + } +} + +void Player2Object::checkSeeking(qint64 elapsed) +{ + if(abs(elapsed - m_previous_pos) > 2000) + { + emit Seeked(elapsed * 1000); + } + m_previous_pos = elapsed; +} + +void Player2Object::playTrack(PlayListTrack *item) +{ + m_pl_manager->selectPlayList((PlayListModel*)sender()); + m_pl_manager->activatePlayList((PlayListModel*)sender()); + disconnect(sender(), SIGNAL(trackAdded(PlayListTrack*)), this, SLOT(playTrack(PlayListTrack*))); + if(!m_pl_manager->currentPlayList()->setCurrent(item)) + return; + m_core->stop(); + m_player->play(); +} + +void Player2Object::disconnectPl() +{ + disconnect(sender(), SIGNAL(trackAdded(PlayListTrack*)), + this, SLOT(playTrack(PlayListTrack*))); +} + +void Player2Object::setModel(PlayListModel *selected, PlayListModel *previous) +{ + if(previous) + disconnect(previous, nullptr, this, nullptr); //disconnect previous model + connect(selected, SIGNAL(listChanged(int)), SLOT(emitPropertiesChanged())); +} + +void Player2Object::syncProperties() +{ + m_props["CanGoNext"] = canGoNext(); + m_props["CanGoPrevious"] = canGoPrevious(); + m_props["CanPause"] = canPause(); + m_props["CanPlay"] = canPlay(); + m_props["CanSeek"] = canSeek(); + m_props["LoopStatus"] = loopStatus(); + m_props["MaximumRate"] = maximumRate(); + m_props["MinimumRate"] = minimumRate(); + m_props["PlaybackStatus"] = playbackStatus(); + m_props["Rate"] = rate(); + m_props["Shuffle"] = shuffle(); + m_props["Volume"] = volume(); + m_props["Metadata"] = metadata(); +} diff --git a/src/plugins/General/mpris/player2object.h b/src/plugins/General/mpris/player2object.h new file mode 100644 index 000000000..af69844a4 --- /dev/null +++ b/src/plugins/General/mpris/player2object.h @@ -0,0 +1,119 @@ +/*************************************************************************** + * Copyright (C) 2010-2015 by Ilya Kotov * + * forkotov02@ya.ru * + * * + * 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 2 of the License, 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, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef PLAYER2OBJECT_H +#define PLAYER2OBJECT_H + +#include +#include +#include +#include +#include +#include + +class SoundCore; +class MediaPlayer; +class PlayListManager; +class PlayListTrack; +class PlayListModel; +class QmmpUiSettings; + +/** + @author Ilya Kotov +*/ +class Player2Object : public QDBusAbstractAdaptor +{ +Q_OBJECT +Q_CLASSINFO("D-Bus Interface", "org.mpris.MediaPlayer2.Player") +Q_PROPERTY(bool CanControl READ canControl) +Q_PROPERTY(bool CanGoNext READ canGoNext) +Q_PROPERTY(bool CanGoPrevious READ canGoPrevious) +Q_PROPERTY(bool CanPause READ canPause) +Q_PROPERTY(bool CanPlay READ canPlay) +Q_PROPERTY(bool CanSeek READ canSeek) +Q_PROPERTY(QString LoopStatus READ loopStatus WRITE setLoopStatus) +Q_PROPERTY(double MaximumRate READ maximumRate) +Q_PROPERTY(QVariantMap Metadata READ metadata) +Q_PROPERTY(double MinimumRate READ minimumRate) +Q_PROPERTY(QString PlaybackStatus READ playbackStatus) +Q_PROPERTY(qlonglong Position READ position) +Q_PROPERTY(double Rate READ rate WRITE setRate) +Q_PROPERTY(bool Shuffle READ shuffle WRITE setShuffle) +Q_PROPERTY(double Volume READ volume WRITE setVolume) + +public: + Player2Object(QObject *parent = nullptr); + virtual ~Player2Object(); + bool canControl() const; + bool canGoNext() const; + bool canGoPrevious() const; + bool canPause() const; + bool canPlay() const; + bool canSeek() const; + QString loopStatus() const; + void setLoopStatus(const QString &value); + double maximumRate() const; + QVariantMap metadata() const; + double minimumRate() const; + QString playbackStatus() const; + qlonglong position() const; + double rate() const; + void setRate(double value); + bool shuffle() const; + void setShuffle(bool value); + double volume() const; + void setVolume(double value); + +public slots: + void Next(); + void OpenUri(const QString &in0); + void Pause(); + void Play(); + void PlayPause(); + void Previous(); + void Seek(qlonglong Offset); + void SetPosition(const QDBusObjectPath &TrackId, qlonglong Position); + void Stop(); +signals: + void Seeked(qlonglong Position); + +private slots: + void emitPropertiesChanged(); + void updateId(); + void checkState(Qmmp::State state); + void checkSeeking(qint64 elapsed); + void playTrack(PlayListTrack *item); + void disconnectPl(); + void setModel(PlayListModel *selected, PlayListModel *previous); + + +private: + void syncProperties(); + SoundCore *m_core; + MediaPlayer *m_player; + PlayListManager *m_pl_manager; + QmmpUiSettings *m_ui_settings; + QMap m_props; + QDBusObjectPath m_trackID; + PlayListTrack *m_prev_track; + qint64 m_previous_pos; + +}; + +#endif diff --git a/src/plugins/General/mpris/root2object.cpp b/src/plugins/General/mpris/root2object.cpp new file mode 100644 index 000000000..a7e9bdd50 --- /dev/null +++ b/src/plugins/General/mpris/root2object.cpp @@ -0,0 +1,91 @@ +/*************************************************************************** + * Copyright (C) 2010-2019 by Ilya Kotov * + * forkotov02@ya.ru * + * * + * 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 2 of the License, 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, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "root2object.h" + +Root2Object::Root2Object(QObject *parent) : QDBusAbstractAdaptor(parent) +{} + + +Root2Object::~Root2Object() +{} + +bool Root2Object::canQuit() const +{ + return true; +} + +bool Root2Object::canRaise() const +{ + return true; +} + +QString Root2Object::desktopEntry() const +{ + return "qmmp"; +} + +bool Root2Object::hasTrackList() const +{ + return false; +} +QString Root2Object::identity() const +{ + return "Qmmp"; +} + +QStringList Root2Object::supportedMimeTypes() const +{ + QStringList mimeTypes; + foreach(DecoderFactory *factory, Decoder::enabledFactories()) + mimeTypes << factory->properties().contentTypes; + foreach(EngineFactory *factory, AbstractEngine::enabledFactories()) + mimeTypes << factory->properties().contentTypes; + mimeTypes.removeDuplicates(); + return mimeTypes; +} + +QStringList Root2Object::supportedUriSchemes() const +{ + QStringList protocols = MetaDataManager::instance()->protocols(); + if(!protocols.contains("file")) //append file if needed + protocols.append("file"); + return protocols; +} + +void Root2Object::Quit() +{ + UiHelper::instance()->exit(); +} + +void Root2Object::Raise() +{ + UiHelper::instance()->showMainWindow(); +} diff --git a/src/plugins/General/mpris/root2object.h b/src/plugins/General/mpris/root2object.h new file mode 100644 index 000000000..762e04655 --- /dev/null +++ b/src/plugins/General/mpris/root2object.h @@ -0,0 +1,58 @@ +/*************************************************************************** + * Copyright (C) 2010-2012 by Ilya Kotov * + * forkotov02@ya.ru * + * * + * 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 2 of the License, 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, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef ROOT2OBJECT_H +#define ROOT2OBJECT_H + +#include +#include + +/** + @author Ilya Kotov +*/ +class Root2Object : public QDBusAbstractAdaptor +{ +Q_OBJECT +Q_CLASSINFO("D-Bus Interface", "org.mpris.MediaPlayer2") +Q_PROPERTY(bool CanQuit READ canQuit) +Q_PROPERTY(bool CanRaise READ canRaise) +Q_PROPERTY(QString DesktopEntry READ desktopEntry) +Q_PROPERTY(bool HasTrackList READ hasTrackList) +Q_PROPERTY(QString Identity READ identity) +Q_PROPERTY(QStringList SupportedMimeTypes READ supportedMimeTypes) +Q_PROPERTY(QStringList SupportedUriSchemes READ supportedUriSchemes) + +public: + Root2Object(QObject *parent = nullptr); + virtual ~Root2Object(); + + bool canQuit() const; + bool canRaise() const; + QString desktopEntry() const; + bool hasTrackList() const; + QString identity() const; + QStringList supportedMimeTypes() const; + QStringList supportedUriSchemes() const; + +public slots: + void Quit(); + void Raise(); +}; + +#endif -- cgit v1.2.3-13-gbd6f