From 7354896a8608d03fa322af144f39bd7faf52cce2 Mon Sep 17 00:00:00 2001 From: Alejandro Wainzinger Date: Fri, 12 Aug 2011 19:35:57 -0700 Subject: [PATCH] Implement remaining MPRIS PropertiesChanged update signals, seeking, etc. --- src/libtomahawk/audio/audioengine.cpp | 38 +++++--- src/libtomahawk/audio/audioengine.h | 3 + .../infoplugins/unix/mprisplugin.cpp | 93 ++++++++++++++++--- .../infosystem/infoplugins/unix/mprisplugin.h | 3 + src/libtomahawk/infosystem/infosystem.h | 1 - 5 files changed, 111 insertions(+), 27 deletions(-) diff --git a/src/libtomahawk/audio/audioengine.cpp b/src/libtomahawk/audio/audioengine.cpp index 5b49cc4e2..924d28da7 100644 --- a/src/libtomahawk/audio/audioengine.cpp +++ b/src/libtomahawk/audio/audioengine.cpp @@ -188,40 +188,52 @@ 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( qint64 ms ) diff --git a/src/libtomahawk/audio/audioengine.h b/src/libtomahawk/audio/audioengine.h index 410eec5d8..685bd7b88 100644 --- a/src/libtomahawk/audio/audioengine.h +++ b/src/libtomahawk/audio/audioengine.h @@ -81,6 +81,9 @@ public slots: void previous(); void next(); + bool canGoPrevious(); + bool canGoNext(); + void seek( qint64 ms ); void seek( int ms ); // for compatibility with seekbar in audiocontrols void setVolume( int percentage ); diff --git a/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp b/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp index ba3498486..00dd631dd 100644 --- a/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp +++ b/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp @@ -49,6 +49,19 @@ MprisPlugin::MprisPlugin() 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 ) ) ); + } @@ -128,31 +141,33 @@ MprisPlugin::canControl() const bool MprisPlugin::canGoNext() const { - return true; + return AudioEngine::instance()->canGoNext(); } bool MprisPlugin::canGoPrevious() const { - return true; + return AudioEngine::instance()->canGoPrevious(); } bool MprisPlugin::canPause() const { - return true; + return AudioEngine::instance()->currentTrack(); } bool MprisPlugin::canPlay() const { - return true; + // 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 false; + return true; } QString @@ -208,7 +223,7 @@ MprisPlugin::metadata() const Tomahawk::result_ptr track = AudioEngine::instance()->currentTrack(); if( track ) { - metadataMap.insert( "mpris:trackid", track->id() ); + 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() ); @@ -322,23 +337,37 @@ 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() ) + 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 @@ -403,8 +432,6 @@ MprisPlugin::audioStarted( const QVariant &input ) { qDebug() << Q_FUNC_INFO; - m_playbackStatus = "Playing"; - if ( !input.canConvert< Tomahawk::InfoSystem::InfoCriteriaHash >() ) return; @@ -412,10 +439,13 @@ MprisPlugin::audioStarted( const QVariant &input ) 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; + //QString nowPlaying = ""; + //qDebug() << "nowPlaying: " << nowPlaying; } void @@ -445,6 +475,43 @@ MprisPlugin::audioResumed( const QVariant &input ) 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 ) diff --git a/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.h b/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.h index a5cc532e4..c36b0cd4d 100644 --- a/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.h +++ b/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.h @@ -146,6 +146,9 @@ protected slots: 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 diff --git a/src/libtomahawk/infosystem/infosystem.h b/src/libtomahawk/infosystem/infosystem.h index 70dd0b219..d20bbd8c3 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,