You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
195 lines
6.6 KiB
195 lines
6.6 KiB
/* |
|
* Copyright 2007-2012 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 "mpris2engine.h" |
|
|
|
#include <QDBusConnection> |
|
#include <QDBusConnectionInterface> |
|
#include <QDBusPendingCallWatcher> |
|
#include <QDBusPendingReply> |
|
#include <QStringList> |
|
|
|
#include "debug.h" |
|
#include "playercontrol.h" |
|
#include "playercontainer.h" |
|
#include "multiplexer.h" |
|
#include "multiplexedservice.h" |
|
|
|
Mpris2Engine::Mpris2Engine(QObject* parent, |
|
const QVariantList& args) |
|
: Plasma::DataEngine(parent, args) |
|
{ |
|
|
|
connect(QDBusConnection::sessionBus().interface(), &QDBusConnectionInterface::serviceOwnerChanged, |
|
this, &Mpris2Engine::serviceOwnerChanged); |
|
|
|
QDBusPendingCall async = QDBusConnection::sessionBus().interface()->asyncCall(QStringLiteral("ListNames")); |
|
QDBusPendingCallWatcher *callWatcher = new QDBusPendingCallWatcher(async, this); |
|
connect(callWatcher, &QDBusPendingCallWatcher::finished, |
|
this, &Mpris2Engine::serviceNameFetchFinished); |
|
} |
|
|
|
Plasma::Service* Mpris2Engine::serviceForSource(const QString& source) |
|
{ |
|
if (source == Multiplexer::sourceName) { |
|
if (!m_multiplexer) { |
|
createMultiplexer(); |
|
} |
|
return new MultiplexedService(m_multiplexer.data(), this); |
|
} else { |
|
PlayerContainer* container = qobject_cast<PlayerContainer*>(containerForSource(source)); |
|
if (container) { |
|
return new PlayerControl(container, this); |
|
} else { |
|
return DataEngine::serviceForSource(source); |
|
} |
|
} |
|
} |
|
|
|
QStringList Mpris2Engine::sources() const |
|
{ |
|
if (m_multiplexer) |
|
return DataEngine::sources(); |
|
else |
|
return DataEngine::sources() << Multiplexer::sourceName; |
|
} |
|
|
|
void Mpris2Engine::serviceOwnerChanged( |
|
const QString& serviceName, |
|
const QString& oldOwner, |
|
const QString& newOwner) |
|
{ |
|
if (!serviceName.startsWith(QLatin1String("org.mpris.MediaPlayer2."))) |
|
return; |
|
|
|
QString sourceName = serviceName.mid(23); |
|
|
|
if (!oldOwner.isEmpty()) { |
|
qCDebug(MPRIS2) << "MPRIS service" << serviceName << "just went offline"; |
|
if (m_multiplexer) { |
|
m_multiplexer.data()->removePlayer(sourceName); |
|
} |
|
removeSource(sourceName); |
|
} |
|
|
|
if (!newOwner.isEmpty()) { |
|
qCDebug(MPRIS2) << "MPRIS service" << serviceName << "just came online"; |
|
addMediaPlayer(serviceName, sourceName); |
|
} |
|
} |
|
|
|
bool Mpris2Engine::updateSourceEvent(const QString& source) |
|
{ |
|
if (source == Multiplexer::sourceName) { |
|
return false; |
|
} else { |
|
PlayerContainer *container = qobject_cast<PlayerContainer*>(containerForSource(source)); |
|
if (container) { |
|
container->refresh(); |
|
return true; |
|
} else { |
|
return false; |
|
} |
|
} |
|
} |
|
|
|
bool Mpris2Engine::sourceRequestEvent(const QString& source) |
|
{ |
|
if (source == Multiplexer::sourceName) { |
|
createMultiplexer(); |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
void Mpris2Engine::initialFetchFinished(PlayerContainer* container) |
|
{ |
|
qCDebug(MPRIS2) << "Props fetch for" << container->objectName() << "finished; adding"; |
|
addSource(container); |
|
if (m_multiplexer) { |
|
m_multiplexer.data()->addPlayer(container); |
|
} |
|
// don't let future refreshes trigger this |
|
disconnect(container, &PlayerContainer::initialFetchFinished, |
|
this, &Mpris2Engine::initialFetchFinished); |
|
disconnect(container, &PlayerContainer::initialFetchFailed, |
|
this, &Mpris2Engine::initialFetchFailed); |
|
} |
|
|
|
void Mpris2Engine::initialFetchFailed(PlayerContainer* container) |
|
{ |
|
qCWarning(MPRIS2) << "Failed to find working MPRIS2 interface for" << container->dbusAddress(); |
|
container->deleteLater(); |
|
} |
|
|
|
void Mpris2Engine::serviceNameFetchFinished(QDBusPendingCallWatcher* watcher) |
|
{ |
|
QDBusPendingReply<QStringList> propsReply = *watcher; |
|
watcher->deleteLater(); |
|
|
|
if (propsReply.isError()) { |
|
qCWarning(MPRIS2) << "Could not get list of available D-Bus services"; |
|
} else { |
|
foreach (const QString& serviceName, propsReply.value()) { |
|
if (serviceName.startsWith(QLatin1String("org.mpris.MediaPlayer2."))) { |
|
qCDebug(MPRIS2) << "Found MPRIS2 service" << serviceName; |
|
// watch out for race conditions; the media player could |
|
// have appeared between starting the service watcher and |
|
// this call being dealt with |
|
// NB: _disappearing_ between sending this call and doing |
|
// this processing is fine |
|
QString sourceName = serviceName.mid(23); |
|
PlayerContainer *container = qobject_cast<PlayerContainer*>(containerForSource(sourceName)); |
|
if (!container) { |
|
qCDebug(MPRIS2) << "Haven't already seen" << serviceName; |
|
addMediaPlayer(serviceName, sourceName); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
void Mpris2Engine::addMediaPlayer(const QString& serviceName, const QString& sourceName) |
|
{ |
|
PlayerContainer *container = new PlayerContainer(serviceName, this); |
|
container->setObjectName(sourceName); |
|
connect(container, &PlayerContainer::initialFetchFinished, |
|
this, &Mpris2Engine::initialFetchFinished); |
|
connect(container, &PlayerContainer::initialFetchFailed, |
|
this, &Mpris2Engine::initialFetchFailed); |
|
} |
|
|
|
void Mpris2Engine::createMultiplexer() |
|
{ |
|
Q_ASSERT (!m_multiplexer); |
|
m_multiplexer = new Multiplexer(this); |
|
|
|
SourceDict dict = containerDict(); |
|
SourceDict::const_iterator i = dict.constBegin(); |
|
while (i != dict.constEnd()) { |
|
PlayerContainer *container = qobject_cast<PlayerContainer*>(i.value()); |
|
m_multiplexer.data()->addPlayer(container); |
|
++i; |
|
} |
|
addSource(m_multiplexer.data()); |
|
} |
|
|
|
K_EXPORT_PLASMA_DATAENGINE_WITH_JSON(mpris2, Mpris2Engine, "plasma-dataengine-mpris2.json") |
|
|
|
#include "mpris2engine.moc" |
|
|
|
|