kde-workspace/plasma/dataengines/nowplaying/playerinterface/mpris/mpris.cpp

397 lines
8.3 KiB
C++
Raw Normal View History

2014-11-13 19:30:51 +02:00
/*
* Copyright 2007 Alex Merry <alex.merry@kdemail.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License version 2 as
* published by the Free Software Foundation
*
* 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 Library 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 "mpris.h"
#include "mpris_p.h"
#include <mprisplayer.h>
#include <QtDBus>
#include <QFile>
#include <kdebug.h>
#include <KIO/NetAccess>
MprisFactory::MprisFactory(QObject* parent)
: DBusPlayerFactory(parent)
{
setObjectName( QLatin1String("MprisFactory" ));
qDBusRegisterMetaType<MprisDBusVersion>();
qDBusRegisterMetaType<MprisDBusStatus>();
}
Player::Ptr MprisFactory::create(const QVariantList& args)
{
if (args.isEmpty()) {
return Player::Ptr(0);
}
QString dbusName(args.first().toString());
if (dbusName.isEmpty()) {
return Player::Ptr(0);
}
Mpris* player = new Mpris(dbusName, this);
if (!player->isRunning()) {
delete player;
player = 0;
}
return Player::Ptr(player);
}
bool MprisFactory::matches(const QString& serviceName)
{
return serviceName.startsWith(QLatin1String("org.mpris")) &&
!serviceName.startsWith(QLatin1String("org.mpris.MediaPlayer2"));
}
Mpris::Mpris(const QString& name, PlayerFactory* factory)
: QObject(),
Player(factory),
m_player(0),
m_playerName(name),
m_artworkLoaded(false)
{
if (!name.startsWith(QLatin1String("org.mpris"))) {
m_playerName = "org.mpris." + name;
}
setName(m_playerName);
setup();
}
Mpris::~Mpris()
{
delete m_player;
}
void Mpris::setup()
{
delete m_player;
m_player = new MprisPlayer(
m_playerName,
"/Player",
QDBusConnection::sessionBus());
m_metadata.clear();
m_state = Stopped;
m_caps = NO_CAPS;
if (m_player->isValid()) {
connect(m_player, SIGNAL(CapsChange(int)),
this, SLOT(capsChanged(int)));
connect(m_player, SIGNAL(TrackChange(QVariantMap)),
this, SLOT(trackChanged(QVariantMap)));
connect(m_player, SIGNAL(StatusChange(MprisDBusStatus)),
this, SLOT(stateChanged(MprisDBusStatus)));
QDBusReply<int> caps = m_player->GetCaps();
if (caps.isValid()) {
capsChanged(caps);
}
QDBusReply<QVariantMap> metadata = m_player->GetMetadata();
if (metadata.isValid()) {
trackChanged(metadata);
}
QDBusReply<MprisDBusStatus> status = m_player->GetStatus();
if (status.isValid()) {
stateChanged(status);
}
}
}
bool Mpris::isRunning()
{
if (!m_player->isValid()) {
setup();
}
return m_player->isValid();
}
Player::State Mpris::state()
{
return m_state;
}
QString Mpris::artist()
{
if (m_metadata.contains("artist")) {
return m_metadata["artist"].toString();
}
return QString();
}
QString Mpris::album()
{
if (m_metadata.contains("album")) {
return m_metadata["album"].toString();
}
return QString();
}
QString Mpris::title()
{
if (m_metadata.contains("title")) {
return m_metadata["title"].toString();
}
return QString();
}
int Mpris::trackNumber()
{
QVariant track;
if (m_metadata.contains("trackNumber")) {
track = m_metadata["trackNumber"];
} else if (m_metadata.contains("tracknumber")) {
track = m_metadata["tracknumber"];
}
if (track.isValid()) {
if (track.canConvert(QVariant::Int)) {
return track.toInt();
} else {
QString text = track.toString();
int pos = text.indexOf('/');
if (pos >= 0) {
text.truncate(pos);
}
return text.toInt();
}
}
return 0;
}
QString Mpris::comment()
{
if (m_metadata.contains("comment")) {
return m_metadata["comment"].toString();
}
return QString();
}
QString Mpris::genre()
{
if (m_metadata.contains("genre")) {
return m_metadata["genre"].toString();
}
return QString();
}
QString Mpris::lyrics()
{
if (m_metadata.contains("lyrics")) {
return m_metadata["lyrics"].toString();
}
return QString();
}
int Mpris::length()
{
if (m_metadata.contains("time")) {
return m_metadata["time"].toInt();
} else if (m_metadata.contains("length")) {
// stupid audacious...
return m_metadata["length"].toInt()/1000;
}
return 0;
}
int Mpris::position()
{
if (m_player->isValid()) {
QDBusReply<int> positionMs = m_player->PositionGet();
if (positionMs.isValid()) {
return positionMs / 1000;
}
}
return 0;
}
float Mpris::volume()
{
if (m_player->isValid()) {
QDBusReply<int> volumePercent = m_player->VolumeGet();
if (volumePercent.isValid())
return ((float)volumePercent) / 100;
}
return 0;
}
QPixmap Mpris::artwork()
{
if (m_artworkLoaded) {
return m_artwork;
}
m_artwork = QPixmap();
const QString arturl = m_metadata["arturl"].toString();
if (!arturl.isEmpty()) {
if (!m_artfiles.contains(arturl) ||
(!m_artfiles[arturl].isEmpty() && !QFile::exists(m_artfiles[arturl]))) {
QString artfile;
if (!KIO::NetAccess::download(arturl, artfile, 0)) {
kWarning() << KIO::NetAccess::lastErrorString();
artfile.clear();
}
m_artfiles[arturl] = artfile;
}
const QString url = m_artfiles[arturl];
if (!url.isEmpty()) {
m_artwork = QPixmap(url);
}
}
m_artworkLoaded = true;
return m_artwork;
}
bool Mpris::canPlay()
{
return m_caps & CAN_PLAY;
}
void Mpris::play()
{
if (m_player->isValid()) {
m_player->Play();
}
}
bool Mpris::canPause()
{
return m_caps & CAN_PAUSE;
}
void Mpris::pause()
{
if (m_player->isValid()) {
m_player->Pause();
}
}
bool Mpris::canStop()
{
return m_state != Stopped;
}
void Mpris::stop()
{
if (m_player->isValid()) {
m_player->Stop();
}
}
bool Mpris::canGoPrevious()
{
return m_caps & CAN_GO_PREV;
}
void Mpris::previous()
{
if (m_player->isValid()) {
m_player->Prev();
}
}
bool Mpris::canGoNext()
{
return m_caps & CAN_GO_NEXT;
}
void Mpris::next()
{
if (m_player->isValid()) {
m_player->Next();
}
}
bool Mpris::canSetVolume()
{
return true;
}
void Mpris::setVolume(qreal volume)
{
if (m_player->isValid()) {
m_player->VolumeSet((int)(volume * 100));
}
}
bool Mpris::canSeek()
{
return m_caps & CAN_SEEK;
}
void Mpris::seek(int time)
{
if (m_player->isValid()) {
// m_player->seek() wants milliseconds
m_player->PositionSet(time * 1000);
}
}
// SLOTS
void Mpris::trackChanged(const QVariantMap& metadata)
{
//kDebug() << m_playerName << "metadata:" << metadata;
const QString oldArt = m_metadata.value("arturl").toString();
m_metadata = metadata;
if (m_artworkLoaded) {
m_artworkLoaded = oldArt == m_metadata.value("arturl");
}
}
void Mpris::stateChanged(MprisDBusStatus state)
{
kDebug() << m_playerName << "state:" << state.play;
switch (state.play) {
case MprisDBusStatus::Playing:
m_state = Playing;
break;
case MprisDBusStatus::Paused:
m_state = Paused;
break;
case MprisDBusStatus::Stopped:
m_state = Stopped;
break;
default:
kDebug() << m_playerName << "unexpected state" << state.play;
}
}
void Mpris::capsChanged(int caps)
{
kDebug() << m_playerName << "capabilities:" << caps;
m_caps = (DBusCaps)caps;
if (!(caps & CAN_PROVIDE_METADATA)) {
m_metadata.clear();
}
}
2015-02-27 09:28:46 +00:00
#include "moc_mpris.cpp"
#include "moc_mpris_p.cpp"