diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt index bde7e14a6..9f4c423e5 100644 --- a/src/libtomahawk/CMakeLists.txt +++ b/src/libtomahawk/CMakeLists.txt @@ -411,10 +411,16 @@ include_directories( . ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/. IF( UNIX AND NOT APPLE ) SET( libSources ${libSources} + infosystem/infoplugins/unix/mprispluginrootadaptor.cpp + infosystem/infoplugins/unix/mprispluginplayeradaptor.cpp + infosystem/infoplugins/unix/mprisplugin.cpp infosystem/infoplugins/unix/fdonotifyplugin.cpp infosystem/infoplugins/unix/imageconverter.cpp ) SET( libHeaders ${libHeaders} + infosystem/infoplugins/unix/mprispluginrootadaptor.h + infosystem/infoplugins/unix/mprispluginplayeradaptor.h + infosystem/infoplugins/unix/mprisplugin.h infosystem/infoplugins/unix/fdonotifyplugin.h ) ENDIF( UNIX AND NOT APPLE ) diff --git a/src/libtomahawk/audio/audioengine.cpp b/src/libtomahawk/audio/audioengine.cpp index 49a55ca14..924d28da7 100644 --- a/src/libtomahawk/audio/audioengine.cpp +++ b/src/libtomahawk/audio/audioengine.cpp @@ -188,43 +188,55 @@ AudioEngine::previous() { tDebug( LOGEXTRA ) << Q_FUNC_INFO; - if ( m_playlist.isNull() ) - return; - - if ( m_playlist.data()->skipRestrictions() == PlaylistInterface::NoSkip || - m_playlist.data()->skipRestrictions() == PlaylistInterface::NoSkipBackwards ) - return; - - loadPreviousTrack(); + if( canGoPrevious() ) + loadPreviousTrack(); } - void AudioEngine::next() { tDebug( LOGEXTRA ) << Q_FUNC_INFO; + if( canGoNext() ) + loadNextTrack(); +} + +bool +AudioEngine::canGoNext() +{ if ( m_playlist.isNull() ) - return; + return false; if ( m_playlist.data()->skipRestrictions() == PlaylistInterface::NoSkip || m_playlist.data()->skipRestrictions() == PlaylistInterface::NoSkipForwards ) - return; + return false; if ( !m_currentTrack.isNull() && !m_playlist.data()->hasNextItem() && m_currentTrack->id() == m_playlist.data()->currentItem()->id() ) { //For instance, when doing a catch-up while listening along, but the person //you're following hasn't started a new track yet...don't do anything - return; + return false; } - loadNextTrack(); + return true; } +bool +AudioEngine::canGoPrevious() +{ + if ( m_playlist.isNull() ) + return false; + + if ( m_playlist.data()->skipRestrictions() == PlaylistInterface::NoSkip || + m_playlist.data()->skipRestrictions() == PlaylistInterface::NoSkipBackwards ) + return false; + + return true; +} void -AudioEngine::seek( int ms ) +AudioEngine::seek( qint64 ms ) { if ( !m_playlist.isNull() && m_playlist.data()->seekRestrictions() == PlaylistInterface::NoSeek ) return; @@ -236,6 +248,11 @@ AudioEngine::seek( int ms ) } } +void +AudioEngine::seek( int ms ) +{ + seek( (qint64) ms ); +} void AudioEngine::setVolume( int percentage ) diff --git a/src/libtomahawk/audio/audioengine.h b/src/libtomahawk/audio/audioengine.h index be6a7ac44..685bd7b88 100644 --- a/src/libtomahawk/audio/audioengine.h +++ b/src/libtomahawk/audio/audioengine.h @@ -69,6 +69,9 @@ public: Tomahawk::result_ptr currentTrack() const { return m_currentTrack; } + qint64 currentTime() const { return m_mediaObject->currentTime(); } + qint64 currentTrackTotalTime() const { return m_mediaObject->totalTime(); } + public slots: void playPause(); void play(); @@ -78,7 +81,11 @@ public slots: void previous(); void next(); - void seek( int ms ); + bool canGoPrevious(); + bool canGoNext(); + + void seek( qint64 ms ); + void seek( int ms ); // for compatibility with seekbar in audiocontrols void setVolume( int percentage ); void lowerVolume() { setVolume( volume() - AUDIO_VOLUME_STEP ); } void raiseVolume() { setVolume( volume() + AUDIO_VOLUME_STEP ); } diff --git a/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp b/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp new file mode 100644 index 000000000..00dd631dd --- /dev/null +++ b/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp @@ -0,0 +1,530 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2010-2011, Christian Muehlhaeuser + * + * Tomahawk 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 + * (at your option) any later version. + * + * Tomahawk 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 Tomahawk. If not, see . + */ + +#include +#include + +#include "audio/audioengine.h" +#include "infosystem/infosystemworker.h" +#include "album.h" +#include "artist.h" +#include "result.h" +#include "tomahawksettings.h" +#include "globalactionmanager.h" +#include "utils/logger.h" + +#include "mprisplugin.h" +#include "mprispluginrootadaptor.h" +#include "mprispluginplayeradaptor.h" + +using namespace Tomahawk::InfoSystem; + +MprisPlugin::MprisPlugin() + : InfoPlugin() +{ + qDebug() << Q_FUNC_INFO; + + m_playbackStatus = "Stopped"; + + m_supportedPushTypes << InfoNowPlaying << InfoNowPaused << InfoNowResumed << InfoNowStopped; + + new MprisPluginRootAdaptor( this ); + new MprisPluginPlayerAdaptor( this ); + QDBusConnection dbus = QDBusConnection::sessionBus(); + dbus.registerObject("/org/mpris/MediaPlayer2", this); + dbus.registerService("org.mpris.MediaPlayer2.tomahawk"); + + connect( AudioEngine::instance(), SIGNAL( volumeChanged( int ) ), + SLOT( onVolumeChanged( int ) ) ); + + // When the playlist changes, signals for several properties are sent + connect( AudioEngine::instance(), SIGNAL( playlistChanged( Tomahawk::PlaylistInterface* ) ), + SLOT( onPlaylistChanged( Tomahawk::PlaylistInterface* ) ) ); + + // When a track is added or removed, CanGoNext updated signal is sent + PlaylistInterface *playlist = AudioEngine::instance()->playlist(); + if( playlist ) + connect( playlist->object(), SIGNAL( trackCountChanged( unsigned int ) ), + SLOT( onTrackCountChanged( unsigned int ) ) ); + +} + + +MprisPlugin::~MprisPlugin() +{ + qDebug() << Q_FUNC_INFO; +} + +// org.mpris.MediaPlayer2 + +bool +MprisPlugin::canQuit() const +{ + qDebug() << Q_FUNC_INFO; + return true; +} + +bool +MprisPlugin::canRaise() const +{ + qDebug() << Q_FUNC_INFO; + return false; +} + +bool +MprisPlugin::hasTrackList() const +{ + qDebug() << Q_FUNC_INFO; + return false; +} + +QString +MprisPlugin::identity() const +{ + return QString("Tomahawk"); +} + +QString +MprisPlugin::desktopEntry() const +{ + return QString("tomahawk"); +} + +QStringList +MprisPlugin::supportedUriSchemes() const +{ + QStringList uriSchemes; + uriSchemes << "tomahawk" << "spotify"; + return uriSchemes; +} + +QStringList +MprisPlugin::supportedMimeTypes() const +{ + return QStringList(); +} + +void +MprisPlugin::Raise() +{ +} + +void +MprisPlugin::Quit() +{ + QApplication::quit(); +} + +// org.mpris.MediaPlayer2.Player + +bool +MprisPlugin::canControl() const +{ + return true; +} + +bool +MprisPlugin::canGoNext() const +{ + return AudioEngine::instance()->canGoNext(); +} + +bool +MprisPlugin::canGoPrevious() const +{ + return AudioEngine::instance()->canGoPrevious(); +} + +bool +MprisPlugin::canPause() const +{ + return AudioEngine::instance()->currentTrack(); +} + +bool +MprisPlugin::canPlay() const +{ + // If there is a currently playing track, or if there is a playlist with at least 1 track, you can hit play + PlaylistInterface *p = AudioEngine::instance()->playlist(); + return AudioEngine::instance()->currentTrack() || ( p && p->trackCount() ); +} + +bool +MprisPlugin::canSeek() const +{ + return true; +} + +QString +MprisPlugin::loopStatus() const +{ + PlaylistInterface *p = AudioEngine::instance()->playlist(); + if (!p) + return "None"; + PlaylistInterface::RepeatMode mode = p->repeatMode(); + switch( mode ) + { + case PlaylistInterface::RepeatOne: + return "Track"; + break; + case PlaylistInterface::RepeatAll: + return "Playlist"; + break; + case PlaylistInterface::NoRepeat: + return "None"; + break; + default: + return QString("None"); + break; + } + + return QString("None"); +} + +void +MprisPlugin::setLoopStatus( const QString &value ) +{ + PlaylistInterface *p = AudioEngine::instance()->playlist(); + if (!p) + return; + if( value == "Track") + p->setRepeatMode( PlaylistInterface::RepeatOne ); + else if( value == "Playlist" ) + p->setRepeatMode( PlaylistInterface::RepeatAll ); + else if( value == "None" ) + p->setRepeatMode( PlaylistInterface::NoRepeat ); +} + +double +MprisPlugin::maximumRate() const +{ + return 1.0; +} + +QVariantMap +MprisPlugin::metadata() const +{ + QVariantMap metadataMap; + Tomahawk::result_ptr track = AudioEngine::instance()->currentTrack(); + if( track ) + { + metadataMap.insert( "mpris:trackid", QString( "/track/" ) + track->id().replace( "-", "" ) ); + metadataMap.insert( "mpris:length", track->duration() ); + metadataMap.insert( "xesam:album", track->album()->name() ); + metadataMap.insert( "xesam:artist", track->artist()->name() ); + metadataMap.insert( "xesam:title", track->track() ); + } + + return metadataMap; +} + +double +MprisPlugin::minimumRate() const +{ + return 1.0; +} + +QString +MprisPlugin::playbackStatus() const +{ + return m_playbackStatus; +} + +qlonglong +MprisPlugin::position() const +{ + // Convert Tomahawk's milliseconds to microseconds + return (qlonglong) ( AudioEngine::instance()->currentTime() * 1000 ); +} + +double +MprisPlugin::rate() const +{ + return 1.0; +} + +void +MprisPlugin::setRate( double value ) +{ + Q_UNUSED( value ); +} + +bool +MprisPlugin::shuffle() const +{ + PlaylistInterface *p = AudioEngine::instance()->playlist(); + if (!p) + return false; + return p->shuffled(); +} + +void +MprisPlugin::setShuffle( bool value ) +{ + PlaylistInterface *p = AudioEngine::instance()->playlist(); + if (!p) + return; + return p->setShuffled( value ); +} + +double +MprisPlugin::volume() const +{ + return AudioEngine::instance()->volume(); +} + +void +MprisPlugin::setVolume( double value ) +{ + AudioEngine::instance()->setVolume( value ); +} + +void +MprisPlugin::Next() +{ + AudioEngine::instance()->next(); +} + +void +MprisPlugin::OpenUri( const QString &Uri ) +{ + if( Uri.contains( "tomahawk://" ) ) + GlobalActionManager::instance()->parseTomahawkLink( Uri ); + else if( Uri.contains( "spotify:" ) ) + GlobalActionManager::instance()->openSpotifyLink( Uri ); +} + +void +MprisPlugin::Pause() +{ + AudioEngine::instance()->pause(); +} + +void +MprisPlugin::Play() +{ + AudioEngine::instance()->play(); +} + +void +MprisPlugin::PlayPause() +{ + AudioEngine::instance()->playPause(); +} + +void +MprisPlugin::Previous() +{ + AudioEngine::instance()->previous(); +} + +void +MprisPlugin::Seek( qlonglong Offset ) +{ + qDebug() << Q_FUNC_INFO; + + qlonglong seekTime = position() + Offset; + qDebug() << "seekTime: " << seekTime; + if( seekTime < 0 ) + AudioEngine::instance()->seek( 0 ); + else if( seekTime > AudioEngine::instance()->currentTrackTotalTime()*1000 ) + Next(); + // seekTime is in microseconds, but we work internally in milliseconds + else + AudioEngine::instance()->seek( (qint64) ( seekTime / 1000 ) ); + +} + +void +MprisPlugin::SetPosition( const QDBusObjectPath &TrackId, qlonglong Position ) +{ + // TODO + qDebug() << Q_FUNC_INFO; + qDebug() << "path: " << TrackId.path(); + qDebug() << "position: " << Position; + + if( TrackId.path() != QString("/track/") + AudioEngine::instance()->currentTrack()->id().replace( "-", "" ) ) + return; + + if( ( Position < 0) || ( Position > AudioEngine::instance()->currentTrackTotalTime()*1000 ) ) + return; + + qDebug() << "seeking to: " << Position/1000 << "ms"; + + AudioEngine::instance()->seek( (qint64) (Position / 1000 ) ); + +} + +void +MprisPlugin::Stop() +{ + AudioEngine::instance()->stop(); +} + +// InfoPlugin Methods + +void +MprisPlugin::getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData ) +{ + qDebug() << Q_FUNC_INFO; + + return; +} + +void +MprisPlugin::pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input ) +{ + qDebug() << Q_FUNC_INFO; + bool isPlayingInfo = false; + + switch ( type ) + { + case InfoNowPlaying: + isPlayingInfo = true; + audioStarted( input ); + break; + case InfoNowPaused: + isPlayingInfo = true; + audioPaused(); + break; + case InfoNowResumed: + isPlayingInfo = true; + audioResumed( input ); + break; + case InfoNowStopped: + isPlayingInfo = true; + audioStopped(); + break; + + default: + break; + } + + if( isPlayingInfo ) + notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "PlaybackStatus"); + +} + +void +MprisPlugin::stateChanged( AudioState newState, AudioState oldState ) +{ + +} + +/** Audio state slots */ +void +MprisPlugin::audioStarted( const QVariant &input ) +{ + qDebug() << Q_FUNC_INFO; + + if ( !input.canConvert< Tomahawk::InfoSystem::InfoCriteriaHash >() ) + return; + + InfoCriteriaHash hash = input.value< Tomahawk::InfoSystem::InfoCriteriaHash >(); + if ( !hash.contains( "title" ) || !hash.contains( "artist" ) ) + return; + + m_playbackStatus = "Playing"; + notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "Metadata"); + + //hash["artist"]; + //hash["title"]; + //QString nowPlaying = ""; + //qDebug() << "nowPlaying: " << nowPlaying; +} + +void +MprisPlugin::audioFinished( const QVariant &input ) +{ + //qDebug() << Q_FUNC_INFO; +} + +void +MprisPlugin::audioStopped() +{ + qDebug() << Q_FUNC_INFO; + m_playbackStatus = "Stopped"; +} + +void +MprisPlugin::audioPaused() +{ + qDebug() << Q_FUNC_INFO; + m_playbackStatus = "Paused"; +} + +void +MprisPlugin::audioResumed( const QVariant &input ) +{ + qDebug() << Q_FUNC_INFO; + audioStarted( input ); +} + +void +MprisPlugin::onVolumeChanged( int volume ) +{ + Q_UNUSED( volume ); + notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "Volume"); +} + +void +MprisPlugin::onPlaylistChanged( Tomahawk::PlaylistInterface* playlist ) +{ + qDebug() << Q_FUNC_INFO; + disconnect( this, SLOT( onTrackCountChanged( unsigned int ) ) ); + qDebug() << "disconnected"; + if( playlist ) + qDebug() << "playlist not null"; + + if( playlist ) + connect( playlist->object(), SIGNAL( trackCountChanged( unsigned int ) ), + SLOT( onTrackCountChanged( unsigned int ) ) ); + + qDebug() << "connected new playlist"; + + // Notify relevant changes + notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "LoopStatus" ); + notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "Shuffle" ); + onTrackCountChanged( 0 ); +} + +void +MprisPlugin::onTrackCountChanged( unsigned int tracks ) +{ + Q_UNUSED( tracks ); + notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "CanGoNext" ); + notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "CanGoPrevious" ); + +} + +void +MprisPlugin::notifyPropertyChanged( const QString& interface, + const QString& propertyName ) +{ + QDBusMessage signal = QDBusMessage::createSignal( + "/org/mpris/MediaPlayer2", + "org.freedesktop.DBus.Properties", + "PropertiesChanged"); + signal << interface; + QVariantMap changedProps; + changedProps.insert(propertyName, property(propertyName.toAscii())); + signal << changedProps; + signal << QStringList(); + QDBusConnection::sessionBus().send(signal); +} + diff --git a/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.h b/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.h new file mode 100644 index 000000000..c36b0cd4d --- /dev/null +++ b/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.h @@ -0,0 +1,174 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2010-2011, Christian Muehlhaeuser + * + * Tomahawk 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 + * (at your option) any later version. + * + * Tomahawk 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 Tomahawk. If not, see . + */ + +#ifndef MPRISPLUGIN_H +#define MPRISPLUGIN_H + +#include "audio/audioengine.h" +#include "infosystem/infosystem.h" + +#include +#include +#include + +namespace Tomahawk { + +namespace InfoSystem { + +class MprisPlugin : public InfoPlugin +{ + Q_OBJECT + +public: + MprisPlugin(); + virtual ~MprisPlugin(); + + // MPRIS DBus Methods + + // org.mpris.MediaPlayer2 + + Q_PROPERTY(bool CanQuit READ canQuit) + bool canQuit() const; + + Q_PROPERTY(bool CanRaise READ canRaise) + bool canRaise() const; + + Q_PROPERTY(QString DesktopEntry READ desktopEntry) + QString desktopEntry() const; + + Q_PROPERTY(bool HasTrackList READ hasTrackList) + bool hasTrackList() const; + + Q_PROPERTY(QString Identity READ identity) + QString identity() const; + + Q_PROPERTY(QStringList SupportedMimeTypes READ supportedMimeTypes) + QStringList supportedMimeTypes() const; + + Q_PROPERTY(QStringList SupportedUriSchemes READ supportedUriSchemes) + QStringList supportedUriSchemes() const; + + // org.mpris.MediaPlayer2.Player + + Q_PROPERTY(bool CanControl READ canControl) + bool canControl() const; + + Q_PROPERTY(bool CanGoNext READ canGoNext) + bool canGoNext() const; + + Q_PROPERTY(bool CanGoPrevious READ canGoPrevious) + bool canGoPrevious() const; + + Q_PROPERTY(bool CanPause READ canPause) + bool canPause() const; + + Q_PROPERTY(bool CanPlay READ canPlay) + bool canPlay() const; + + Q_PROPERTY(bool CanSeek READ canSeek) + bool canSeek() const; + + Q_PROPERTY(QString LoopStatus READ loopStatus WRITE setLoopStatus) + QString loopStatus() const; + void setLoopStatus(const QString &value); + + Q_PROPERTY(double MaximumRate READ maximumRate) + double maximumRate() const; + + Q_PROPERTY(QVariantMap Metadata READ metadata) + QVariantMap metadata() const; + + Q_PROPERTY(double MinimumRate READ minimumRate) + double minimumRate() const; + + Q_PROPERTY(QString PlaybackStatus READ playbackStatus) + QString playbackStatus() const; + + Q_PROPERTY(qlonglong Position READ position) + qlonglong position() const; + + Q_PROPERTY(double Rate READ rate WRITE setRate) + double rate() const; + void setRate(double value); + + Q_PROPERTY(bool Shuffle READ shuffle WRITE setShuffle) + bool shuffle() const; + void setShuffle(bool value); + + Q_PROPERTY(double Volume READ volume WRITE setVolume) + double volume() const; + void setVolume(double value); + +public slots: + void namChangedSlot( QNetworkAccessManager* /*nam*/ ) {} // unused + + virtual void notInCacheSlot( uint requestId, const Tomahawk::InfoSystem::InfoCriteriaHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData ) + { + Q_UNUSED( requestId ); + Q_UNUSED( criteria ); + Q_UNUSED( requestData ); + } + + // org.mpris.MediaPlayer2 + void Raise(); + void Quit(); + + // org.mpris.MediaPlayer2.Player + void Next(); + void OpenUri(const QString &Uri); + void Pause(); + void Play(); + void PlayPause(); + void Previous(); + void Seek(qlonglong Offset); + void SetPosition(const QDBusObjectPath &TrackId, qlonglong Position); + void Stop(); + + +protected slots: + void getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData ); + void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input ); + +private slots: + void stateChanged( AudioState newState, AudioState oldState ); + void onVolumeChanged( int volume ); + void onPlaylistChanged( Tomahawk::PlaylistInterface* playlist); + void onTrackCountChanged( unsigned int tracks ); + +private: + // Get Info + + // Push Info + void audioStarted( const QVariant &input ); + void audioFinished( const QVariant &input ); + void audioStopped(); + void audioPaused(); + void audioResumed( const QVariant &input ); + + // DBus + void notifyPropertyChanged( const QString& interface, const QString& propertyName ); + QString m_playbackStatus; + +}; + +}; + + +} + +#endif // MPRISPLUGIN_H diff --git a/src/libtomahawk/infosystem/infoplugins/unix/mprispluginplayeradaptor.cpp b/src/libtomahawk/infosystem/infoplugins/unix/mprispluginplayeradaptor.cpp new file mode 100644 index 000000000..c1a155b2d --- /dev/null +++ b/src/libtomahawk/infosystem/infoplugins/unix/mprispluginplayeradaptor.cpp @@ -0,0 +1,205 @@ +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -a mprispluginplayeradaptor -c MprisPluginPlayerAdaptor mprispluginplayeradaptor.xml + * + * qdbusxml2cpp is Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#include "mprispluginplayeradaptor.h" +#include +#include +#include +#include +#include +#include +#include + +/* + * Implementation of adaptor class MprisPluginPlayerAdaptor + */ + +MprisPluginPlayerAdaptor::MprisPluginPlayerAdaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + // constructor + setAutoRelaySignals(true); +} + +MprisPluginPlayerAdaptor::~MprisPluginPlayerAdaptor() +{ + // destructor +} + +bool MprisPluginPlayerAdaptor::canControl() const +{ + // get the value of property CanControl + return qvariant_cast< bool >(parent()->property("CanControl")); +} + +bool MprisPluginPlayerAdaptor::canGoNext() const +{ + // get the value of property CanGoNext + return qvariant_cast< bool >(parent()->property("CanGoNext")); +} + +bool MprisPluginPlayerAdaptor::canGoPrevious() const +{ + // get the value of property CanGoPrevious + return qvariant_cast< bool >(parent()->property("CanGoPrevious")); +} + +bool MprisPluginPlayerAdaptor::canPause() const +{ + // get the value of property CanPause + return qvariant_cast< bool >(parent()->property("CanPause")); +} + +bool MprisPluginPlayerAdaptor::canPlay() const +{ + // get the value of property CanPlay + return qvariant_cast< bool >(parent()->property("CanPlay")); +} + +bool MprisPluginPlayerAdaptor::canSeek() const +{ + // get the value of property CanSeek + return qvariant_cast< bool >(parent()->property("CanSeek")); +} + +QString MprisPluginPlayerAdaptor::loopStatus() const +{ + // get the value of property LoopStatus + return qvariant_cast< QString >(parent()->property("LoopStatus")); +} + +void MprisPluginPlayerAdaptor::setLoopStatus(const QString &value) +{ + // set the value of property LoopStatus + parent()->setProperty("LoopStatus", qVariantFromValue(value)); +} + +double MprisPluginPlayerAdaptor::maximumRate() const +{ + // get the value of property MaximumRate + return qvariant_cast< double >(parent()->property("MaximumRate")); +} + +QVariantMap MprisPluginPlayerAdaptor::metadata() const +{ + // get the value of property Metadata + return qvariant_cast< QVariantMap >(parent()->property("Metadata")); +} + +double MprisPluginPlayerAdaptor::minimumRate() const +{ + // get the value of property MinimumRate + return qvariant_cast< double >(parent()->property("MinimumRate")); +} + +QString MprisPluginPlayerAdaptor::playbackStatus() const +{ + // get the value of property PlaybackStatus + return qvariant_cast< QString >(parent()->property("PlaybackStatus")); +} + +qlonglong MprisPluginPlayerAdaptor::position() const +{ + // get the value of property Position + return qvariant_cast< qlonglong >(parent()->property("Position")); +} + +double MprisPluginPlayerAdaptor::rate() const +{ + // get the value of property Rate + return qvariant_cast< double >(parent()->property("Rate")); +} + +void MprisPluginPlayerAdaptor::setRate(double value) +{ + // set the value of property Rate + parent()->setProperty("Rate", qVariantFromValue(value)); +} + +bool MprisPluginPlayerAdaptor::shuffle() const +{ + // get the value of property Shuffle + return qvariant_cast< bool >(parent()->property("Shuffle")); +} + +void MprisPluginPlayerAdaptor::setShuffle(bool value) +{ + // set the value of property Shuffle + parent()->setProperty("Shuffle", qVariantFromValue(value)); +} + +double MprisPluginPlayerAdaptor::volume() const +{ + // get the value of property Volume + return qvariant_cast< double >(parent()->property("Volume")); +} + +void MprisPluginPlayerAdaptor::setVolume(double value) +{ + // set the value of property Volume + parent()->setProperty("Volume", qVariantFromValue(value)); +} + +void MprisPluginPlayerAdaptor::Next() +{ + // handle method call org.mpris.MediaPlayer2.Player.Next + QMetaObject::invokeMethod(parent(), "Next"); +} + +void MprisPluginPlayerAdaptor::OpenUri(const QString &Uri) +{ + // handle method call org.mpris.MediaPlayer2.Player.OpenUri + QMetaObject::invokeMethod(parent(), "OpenUri", Q_ARG(QString, Uri)); +} + +void MprisPluginPlayerAdaptor::Pause() +{ + // handle method call org.mpris.MediaPlayer2.Player.Pause + QMetaObject::invokeMethod(parent(), "Pause"); +} + +void MprisPluginPlayerAdaptor::Play() +{ + // handle method call org.mpris.MediaPlayer2.Player.Play + QMetaObject::invokeMethod(parent(), "Play"); +} + +void MprisPluginPlayerAdaptor::PlayPause() +{ + // handle method call org.mpris.MediaPlayer2.Player.PlayPause + QMetaObject::invokeMethod(parent(), "PlayPause"); +} + +void MprisPluginPlayerAdaptor::Previous() +{ + // handle method call org.mpris.MediaPlayer2.Player.Previous + QMetaObject::invokeMethod(parent(), "Previous"); +} + +void MprisPluginPlayerAdaptor::Seek(qlonglong Offset) +{ + qDebug() << Q_FUNC_INFO; + // handle method call org.mpris.MediaPlayer2.Player.Seek + QMetaObject::invokeMethod(parent(), "Seek", Q_ARG(qlonglong, Offset)); +} + +void MprisPluginPlayerAdaptor::SetPosition(const QDBusObjectPath &TrackId, qlonglong Position) +{ + qDebug() << Q_FUNC_INFO; + // handle method call org.mpris.MediaPlayer2.Player.SetPosition + QMetaObject::invokeMethod(parent(), "SetPosition", Q_ARG(QDBusObjectPath, TrackId), Q_ARG(qlonglong, Position)); +} + +void MprisPluginPlayerAdaptor::Stop() +{ + // handle method call org.mpris.MediaPlayer2.Player.Stop + QMetaObject::invokeMethod(parent(), "Stop"); +} + diff --git a/src/libtomahawk/infosystem/infoplugins/unix/mprispluginplayeradaptor.h b/src/libtomahawk/infosystem/infoplugins/unix/mprispluginplayeradaptor.h new file mode 100644 index 000000000..d94cfc90e --- /dev/null +++ b/src/libtomahawk/infosystem/infoplugins/unix/mprispluginplayeradaptor.h @@ -0,0 +1,139 @@ +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -a mprispluginplayeradaptor -c MprisPluginPlayerAdaptor mprispluginplayeradaptor.xml + * + * qdbusxml2cpp is Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#ifndef MPRISPLUGINPLAYERADAPTOR_H_1313089554 +#define MPRISPLUGINPLAYERADAPTOR_H_1313089554 + +#include +#include +class QByteArray; +template class QList; +template class QMap; +class QString; +class QStringList; +class QVariant; + +/* + * Adaptor class for interface org.mpris.MediaPlayer2.Player + */ +class MprisPluginPlayerAdaptor: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.mpris.MediaPlayer2.Player") + Q_CLASSINFO("D-Bus Introspection", "" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" + "") +public: + MprisPluginPlayerAdaptor(QObject *parent); + virtual ~MprisPluginPlayerAdaptor(); + +public: // PROPERTIES + Q_PROPERTY(bool CanControl READ canControl) + bool canControl() const; + + Q_PROPERTY(bool CanGoNext READ canGoNext) + bool canGoNext() const; + + Q_PROPERTY(bool CanGoPrevious READ canGoPrevious) + bool canGoPrevious() const; + + Q_PROPERTY(bool CanPause READ canPause) + bool canPause() const; + + Q_PROPERTY(bool CanPlay READ canPlay) + bool canPlay() const; + + Q_PROPERTY(bool CanSeek READ canSeek) + bool canSeek() const; + + Q_PROPERTY(QString LoopStatus READ loopStatus WRITE setLoopStatus) + QString loopStatus() const; + void setLoopStatus(const QString &value); + + Q_PROPERTY(double MaximumRate READ maximumRate) + double maximumRate() const; + + Q_PROPERTY(QVariantMap Metadata READ metadata) + QVariantMap metadata() const; + + Q_PROPERTY(double MinimumRate READ minimumRate) + double minimumRate() const; + + Q_PROPERTY(QString PlaybackStatus READ playbackStatus) + QString playbackStatus() const; + + Q_PROPERTY(qlonglong Position READ position) + qlonglong position() const; + + Q_PROPERTY(double Rate READ rate WRITE setRate) + double rate() const; + void setRate(double value); + + Q_PROPERTY(bool Shuffle READ shuffle WRITE setShuffle) + bool shuffle() const; + void setShuffle(bool value); + + Q_PROPERTY(double Volume READ volume WRITE setVolume) + double volume() const; + void setVolume(double value); + +public Q_SLOTS: // METHODS + void Next(); + void OpenUri(const QString &Uri); + void Pause(); + void Play(); + void PlayPause(); + void Previous(); + void Seek(qlonglong Offset); + void SetPosition(const QDBusObjectPath &TrackId, qlonglong Position); + void Stop(); +Q_SIGNALS: // SIGNALS + void Seeked(qlonglong Position); +}; + +#endif diff --git a/src/libtomahawk/infosystem/infoplugins/unix/mprispluginplayeradaptor.xml b/src/libtomahawk/infosystem/infoplugins/unix/mprispluginplayeradaptor.xml new file mode 100644 index 000000000..4a7fc214b --- /dev/null +++ b/src/libtomahawk/infosystem/infoplugins/unix/mprispluginplayeradaptor.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/libtomahawk/infosystem/infoplugins/unix/mprispluginrootadaptor.cpp b/src/libtomahawk/infosystem/infoplugins/unix/mprispluginrootadaptor.cpp new file mode 100644 index 000000000..0307ca836 --- /dev/null +++ b/src/libtomahawk/infosystem/infoplugins/unix/mprispluginrootadaptor.cpp @@ -0,0 +1,92 @@ +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -a mprispluginrootadaptor -c MprisPluginRootAdaptor mprispluginrootadaptor.xml + * + * qdbusxml2cpp is Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#include "mprispluginrootadaptor.h" +#include +#include +#include +#include +#include +#include +#include + +/* + * Implementation of adaptor class MprisPluginRootAdaptor + */ + +MprisPluginRootAdaptor::MprisPluginRootAdaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + // constructor + setAutoRelaySignals(true); +} + +MprisPluginRootAdaptor::~MprisPluginRootAdaptor() +{ + // destructor +} + +bool MprisPluginRootAdaptor::canQuit() const +{ + // get the value of property CanQuit + return qvariant_cast< bool >(parent()->property("CanQuit")); +} + +bool MprisPluginRootAdaptor::canRaise() const +{ + qDebug() << Q_FUNC_INFO; + // get the value of property CanRaise + bool ret = qvariant_cast< bool >(parent()->property("CanRaise")); + qDebug() << "ret: " << ret; + return ret; +} + +QString MprisPluginRootAdaptor::desktopEntry() const +{ + // get the value of property DesktopEntry + return qvariant_cast< QString >(parent()->property("DesktopEntry")); +} + +bool MprisPluginRootAdaptor::hasTrackList() const +{ + // get the value of property HasTrackList + return qvariant_cast< bool >(parent()->property("HasTrackList")); +} + +QString MprisPluginRootAdaptor::identity() const +{ + // get the value of property Identity + return qvariant_cast< QString >(parent()->property("Identity")); +} + +QStringList MprisPluginRootAdaptor::supportedMimeTypes() const +{ + // get the value of property SupportedMimeTypes + return qvariant_cast< QStringList >(parent()->property("SupportedMimeTypes")); +} + +QStringList MprisPluginRootAdaptor::supportedUriSchemes() const +{ + // get the value of property SupportedUriSchemes + return qvariant_cast< QStringList >(parent()->property("SupportedUriSchemes")); +} + +void MprisPluginRootAdaptor::Quit() +{ + // handle method call org.mpris.MediaPlayer2.Quit + QMetaObject::invokeMethod(parent(), "Quit"); +} + +void MprisPluginRootAdaptor::Raise() +{ + // handle method call org.mpris.MediaPlayer2.Raise + QMetaObject::invokeMethod(parent(), "Raise"); +} + diff --git a/src/libtomahawk/infosystem/infoplugins/unix/mprispluginrootadaptor.h b/src/libtomahawk/infosystem/infoplugins/unix/mprispluginrootadaptor.h new file mode 100644 index 000000000..ac4895bc4 --- /dev/null +++ b/src/libtomahawk/infosystem/infoplugins/unix/mprispluginrootadaptor.h @@ -0,0 +1,76 @@ +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -a mprispluginrootadaptor -c MprisPluginRootAdaptor mprispluginrootadaptor.xml + * + * qdbusxml2cpp is Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#ifndef MPRISPLUGINROOTADAPTOR_H_1312900930 +#define MPRISPLUGINROOTADAPTOR_H_1312900930 + +#include +#include +class QByteArray; +template class QList; +template class QMap; +class QString; +class QStringList; +class QVariant; + +/* + * Adaptor class for interface org.mpris.MediaPlayer2 + */ +class MprisPluginRootAdaptor: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.mpris.MediaPlayer2") + Q_CLASSINFO("D-Bus Introspection", "" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" + "") +public: + MprisPluginRootAdaptor(QObject *parent); + virtual ~MprisPluginRootAdaptor(); + +public: // PROPERTIES + Q_PROPERTY(bool CanQuit READ canQuit) + bool canQuit() const; + + Q_PROPERTY(bool CanRaise READ canRaise) + bool canRaise() const; + + Q_PROPERTY(QString DesktopEntry READ desktopEntry) + QString desktopEntry() const; + + Q_PROPERTY(bool HasTrackList READ hasTrackList) + bool hasTrackList() const; + + Q_PROPERTY(QString Identity READ identity) + QString identity() const; + + Q_PROPERTY(QStringList SupportedMimeTypes READ supportedMimeTypes) + QStringList supportedMimeTypes() const; + + Q_PROPERTY(QStringList SupportedUriSchemes READ supportedUriSchemes) + QStringList supportedUriSchemes() const; + +public Q_SLOTS: // METHODS + void Quit(); + void Raise(); +Q_SIGNALS: // SIGNALS +}; + +#endif diff --git a/src/libtomahawk/infosystem/infoplugins/unix/mprispluginrootadaptor.xml b/src/libtomahawk/infosystem/infoplugins/unix/mprispluginrootadaptor.xml new file mode 100644 index 000000000..50ee35e24 --- /dev/null +++ b/src/libtomahawk/infosystem/infoplugins/unix/mprispluginrootadaptor.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/libtomahawk/infosystem/infosystem.cpp b/src/libtomahawk/infosystem/infosystem.cpp index 9bc46a1f6..973be3844 100644 --- a/src/libtomahawk/infosystem/infosystem.cpp +++ b/src/libtomahawk/infosystem/infosystem.cpp @@ -58,14 +58,16 @@ InfoSystem::InfoSystem( QObject *parent ) qDebug() << Q_FUNC_INFO; - m_infoSystemCacheThreadController = new QThread( this ); + m_infoSystemCacheThreadController = new InfoSystemCacheThread( this ); m_cache = QWeakPointer< InfoSystemCache >( new InfoSystemCache() ); m_cache.data()->moveToThread( m_infoSystemCacheThreadController ); + m_infoSystemCacheThreadController->setCache( m_cache ); m_infoSystemCacheThreadController->start( QThread::IdlePriority ); - m_infoSystemWorkerThreadController = new QThread( this ); - m_worker = QWeakPointer< InfoSystemWorker>( new InfoSystemWorker() ); + m_infoSystemWorkerThreadController = new InfoSystemWorkerThread( this ); + m_worker = QWeakPointer< InfoSystemWorker >( new InfoSystemWorker() ); m_worker.data()->moveToThread( m_infoSystemWorkerThreadController ); + m_infoSystemWorkerThreadController->setWorker( m_worker ); m_infoSystemWorkerThreadController->start(); QMetaObject::invokeMethod( m_worker.data(), "init", Qt::QueuedConnection, Q_ARG( QWeakPointer< Tomahawk::InfoSystem::InfoSystemCache >, m_cache ) ); @@ -89,7 +91,7 @@ InfoSystem::~InfoSystem() m_infoSystemWorkerThreadController->quit(); m_infoSystemWorkerThreadController->wait( 60000 ); - delete m_worker.data(); + //delete m_worker.data(); delete m_infoSystemWorkerThreadController; m_infoSystemWorkerThreadController = 0; } @@ -100,7 +102,7 @@ InfoSystem::~InfoSystem() m_infoSystemCacheThreadController->quit(); m_infoSystemCacheThreadController->wait( 60000 ); - delete m_cache.data(); + //delete m_cache.data(); delete m_infoSystemCacheThreadController; m_infoSystemCacheThreadController = 0; } @@ -155,6 +157,65 @@ InfoSystem::pushInfo( const QString &caller, const InfoTypeMap &input ) QMetaObject::invokeMethod( m_worker.data(), "pushInfo", Qt::QueuedConnection, Q_ARG( QString, caller ), Q_ARG( Tomahawk::InfoSystem::InfoType, type ), Q_ARG( QVariant, input[ type ] ) ); } + +InfoSystemCacheThread::InfoSystemCacheThread( QObject *parent ) + : QThread( parent ) +{ +} + +InfoSystemCacheThread::~InfoSystemCacheThread() +{ + delete m_cache.data(); +} + +void +InfoSystemCacheThread::InfoSystemCacheThread::run() +{ + exec(); +} + +QWeakPointer< InfoSystemCache > +InfoSystemCacheThread::cache() const +{ + return m_cache; +} + +void +InfoSystemCacheThread::setCache( QWeakPointer< InfoSystemCache > cache ) +{ + m_cache = cache; +} + +InfoSystemWorkerThread::InfoSystemWorkerThread( QObject *parent ) + : QThread( parent ) +{ +} + +InfoSystemWorkerThread::~InfoSystemWorkerThread() +{ +} + +void +InfoSystemWorkerThread::InfoSystemWorkerThread::run() +{ + exec(); + if( m_worker ) + delete m_worker.data(); +} + +QWeakPointer< InfoSystemWorker > +InfoSystemWorkerThread::worker() const +{ + return m_worker; +} + +void +InfoSystemWorkerThread::setWorker( QWeakPointer< InfoSystemWorker > worker ) +{ + m_worker = worker; +} + + } //namespace InfoSystem } //namespace Tomahawk diff --git a/src/libtomahawk/infosystem/infosystem.h b/src/libtomahawk/infosystem/infosystem.h index 70dd0b219..c918970cb 100644 --- a/src/libtomahawk/infosystem/infosystem.h +++ b/src/libtomahawk/infosystem/infosystem.h @@ -102,7 +102,6 @@ enum InfoType { // as items are saved in cache, mark them here to not change the InfoNowPaused = 81, InfoNowResumed = 82, InfoNowStopped = 83, - InfoLove = 90, InfoUnLove = 91, @@ -160,6 +159,38 @@ private: typedef QWeakPointer< InfoPlugin > InfoPluginPtr; +class InfoSystemCacheThread : public QThread +{ + Q_OBJECT + +public: + InfoSystemCacheThread( QObject *parent ); + virtual ~InfoSystemCacheThread(); + + void run(); + QWeakPointer< InfoSystemCache > cache() const; + void setCache( QWeakPointer< InfoSystemCache > cache ); + +private: + QWeakPointer< InfoSystemCache > m_cache; +}; + +class InfoSystemWorkerThread : public QThread +{ + Q_OBJECT + +public: + InfoSystemWorkerThread( QObject *parent ); + virtual ~InfoSystemWorkerThread(); + + void run(); + QWeakPointer< InfoSystemWorker > worker() const; + void setWorker( QWeakPointer< InfoSystemWorker > worker ); + +private: + QWeakPointer< InfoSystemWorker > m_worker; +}; + class DLLEXPORT InfoSystem : public QObject { Q_OBJECT @@ -186,8 +217,8 @@ public slots: private: QWeakPointer< InfoSystemCache > m_cache; QWeakPointer< InfoSystemWorker > m_worker; - QThread* m_infoSystemCacheThreadController; - QThread* m_infoSystemWorkerThreadController; + InfoSystemCacheThread* m_infoSystemCacheThreadController; + InfoSystemWorkerThread* m_infoSystemWorkerThreadController; static InfoSystem* s_instance; }; @@ -196,6 +227,8 @@ private: } + + inline uint qHash( Tomahawk::InfoSystem::InfoCriteriaHash hash ) { QCryptographicHash md5( QCryptographicHash::Md5 ); diff --git a/src/libtomahawk/infosystem/infosystemworker.cpp b/src/libtomahawk/infosystem/infosystemworker.cpp index eea9a27ea..7b11ded1f 100644 --- a/src/libtomahawk/infosystem/infosystemworker.cpp +++ b/src/libtomahawk/infosystem/infosystemworker.cpp @@ -35,6 +35,7 @@ #endif #ifdef Q_WS_X11 #include "infoplugins/unix/fdonotifyplugin.h" +#include "infoplugins/unix/mprisplugin.h" #endif #include "lastfm/NetworkAccessManager" @@ -97,6 +98,9 @@ InfoSystemWorker::init( QWeakPointer< Tomahawk::InfoSystem::InfoSystemCache> cac InfoPluginPtr fdonotifyptr( new FdoNotifyPlugin() ); m_plugins.append( fdonotifyptr ); registerInfoTypes( fdonotifyptr, fdonotifyptr.data()->supportedGetTypes(), fdonotifyptr.data()->supportedPushTypes() ); + InfoPluginPtr mprisptr( new MprisPlugin() ); + m_plugins.append( mprisptr ); + registerInfoTypes( mprisptr, mprisptr.data()->supportedGetTypes(), mprisptr.data()->supportedPushTypes() ); #endif Q_FOREACH( InfoPluginPtr plugin, m_plugins ) diff --git a/src/libtomahawk/playlistinterface.h b/src/libtomahawk/playlistinterface.h index 9f46a3b11..f4c6650a1 100644 --- a/src/libtomahawk/playlistinterface.h +++ b/src/libtomahawk/playlistinterface.h @@ -36,12 +36,16 @@ class DLLEXPORT PlaylistInterface public: enum RepeatMode { NoRepeat, RepeatOne, RepeatAll }; + Q_ENUMS( RepeatMode ) enum ViewMode { Unknown, Tree, Flat, Album }; enum SeekRestrictions { NoSeekRestrictions, NoSeek }; enum SkipRestrictions { NoSkipRestrictions, NoSkipForwards, NoSkipBackwards, NoSkip }; enum RetryMode { NoRetry, Retry }; - PlaylistInterface( QObject* parent = 0 ) : m_object( parent ) {} + PlaylistInterface( QObject* parent = 0 ) : m_object( parent ) + { + qRegisterMetaType( "Tomahawk::PlaylistInterface::RepeatMode" ); + } virtual ~PlaylistInterface() {} virtual QList< Tomahawk::query_ptr > tracks() = 0;