mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-08-09 07:36:48 +02:00
Make a Last FM InfoSystem plugin and use it to handle now playing and scrobbling
This commit is contained in:
@@ -83,6 +83,9 @@ enum InfoType {
|
|||||||
InfoMiscTopHotttness,
|
InfoMiscTopHotttness,
|
||||||
InfoMiscTopTerms,
|
InfoMiscTopTerms,
|
||||||
|
|
||||||
|
InfoMiscSubmitNowPlaying,
|
||||||
|
InfoMiscSubmitScrobble,
|
||||||
|
|
||||||
InfoNoInfo
|
InfoNoInfo
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -36,6 +36,7 @@ SET( tomahawkSources ${tomahawkSources}
|
|||||||
|
|
||||||
infosystem/infosystem.cpp
|
infosystem/infosystem.cpp
|
||||||
infosystem/infoplugins/echonestplugin.cpp
|
infosystem/infoplugins/echonestplugin.cpp
|
||||||
|
infosystem/infoplugins/lastfmplugin.cpp
|
||||||
infosystem/infoplugins/musixmatchplugin.cpp
|
infosystem/infoplugins/musixmatchplugin.cpp
|
||||||
|
|
||||||
web/api_v1.cpp
|
web/api_v1.cpp
|
||||||
@@ -77,6 +78,7 @@ SET( tomahawkHeaders ${tomahawkHeaders}
|
|||||||
sip/SipHandler.h
|
sip/SipHandler.h
|
||||||
|
|
||||||
infosystem/infoplugins/echonestplugin.h
|
infosystem/infoplugins/echonestplugin.h
|
||||||
|
infosystem/infoplugins/lastfmplugin.h
|
||||||
infosystem/infoplugins/musixmatchplugin.h
|
infosystem/infoplugins/musixmatchplugin.h
|
||||||
|
|
||||||
web/api_v1.h
|
web/api_v1.h
|
||||||
|
251
src/infosystem/infoplugins/lastfmplugin.cpp
Normal file
251
src/infosystem/infoplugins/lastfmplugin.cpp
Normal file
@@ -0,0 +1,251 @@
|
|||||||
|
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||||
|
*
|
||||||
|
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lastfmplugin.h"
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QSettings>
|
||||||
|
#include <QCryptographicHash>
|
||||||
|
|
||||||
|
#include "album.h"
|
||||||
|
#include "typedefs.h"
|
||||||
|
#include "audio/audioengine.h"
|
||||||
|
#include "tomahawksettings.h"
|
||||||
|
#include "tomahawk/tomahawkapp.h"
|
||||||
|
|
||||||
|
#include <lastfm/ws.h>
|
||||||
|
#include <lastfm/XmlQuery>
|
||||||
|
|
||||||
|
using namespace Tomahawk::InfoSystem;
|
||||||
|
|
||||||
|
static QString
|
||||||
|
md5( const QByteArray& src )
|
||||||
|
{
|
||||||
|
QByteArray const digest = QCryptographicHash::hash( src, QCryptographicHash::Md5 );
|
||||||
|
return QString::fromLatin1( digest.toHex() ).rightJustified( 32, '0' );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LastFmPlugin::LastFmPlugin( QObject* parent )
|
||||||
|
: InfoPlugin(parent)
|
||||||
|
, m_scrobbler( 0 )
|
||||||
|
, m_authJob( 0 )
|
||||||
|
{
|
||||||
|
QSet< InfoType > supportedTypes;
|
||||||
|
supportedTypes << Tomahawk::InfoSystem::InfoMiscSubmitScrobble << Tomahawk::InfoSystem::InfoMiscSubmitNowPlaying;
|
||||||
|
qobject_cast< InfoSystem* >(parent)->registerInfoTypes(this, supportedTypes);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Your API Key is 7194b85b6d1f424fe1668173a78c0c4a
|
||||||
|
Your secret is ba80f1df6d27ae63e9cb1d33ccf2052f
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Flush session key cache
|
||||||
|
TomahawkSettings::instance()->setLastFmSessionKey( QByteArray() );
|
||||||
|
|
||||||
|
lastfm::ws::ApiKey = "7194b85b6d1f424fe1668173a78c0c4a";
|
||||||
|
lastfm::ws::SharedSecret = "ba80f1df6d27ae63e9cb1d33ccf2052f";
|
||||||
|
lastfm::ws::Username = TomahawkSettings::instance()->lastFmUsername();
|
||||||
|
|
||||||
|
m_pw = TomahawkSettings::instance()->lastFmPassword();
|
||||||
|
|
||||||
|
if( TomahawkSettings::instance()->scrobblingEnabled() && !lastfm::ws::Username.isEmpty() )
|
||||||
|
{
|
||||||
|
createScrobbler();
|
||||||
|
}
|
||||||
|
|
||||||
|
//HACK work around a bug in liblastfm---it doesn't create its config dir, so when it
|
||||||
|
// tries to write the track cache, it fails silently. until we have a fixed version, do this
|
||||||
|
// code taken from Amarok (src/services/lastfm/ScrobblerAdapter.cpp)
|
||||||
|
#ifdef Q_WS_X11
|
||||||
|
QString lpath = QDir::home().filePath( ".local/share/Last.fm" );
|
||||||
|
QDir ldir = QDir( lpath );
|
||||||
|
if( !ldir.exists() )
|
||||||
|
{
|
||||||
|
ldir.mkpath( lpath );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
connect( TomahawkSettings::instance(), SIGNAL( changed() ),
|
||||||
|
SLOT( settingsChanged() ), Qt::QueuedConnection );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LastFmPlugin::~LastFmPlugin()
|
||||||
|
{
|
||||||
|
delete m_scrobbler;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LastFmPlugin::getInfo( const QString &caller, const InfoType type, const QVariant& data, Tomahawk::InfoSystem::InfoCustomDataHash customData )
|
||||||
|
{
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
if ( type == InfoMiscSubmitNowPlaying )
|
||||||
|
nowPlaying( caller, type, data, customData );
|
||||||
|
else if ( type == InfoMiscSubmitScrobble )
|
||||||
|
scrobble( caller, type, data, customData );
|
||||||
|
else
|
||||||
|
dataError( caller, type, data, customData );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LastFmPlugin::nowPlaying( const QString &caller, const InfoType type, const QVariant& data, Tomahawk::InfoSystem::InfoCustomDataHash &customData )
|
||||||
|
{
|
||||||
|
if ( !data.canConvert< Tomahawk::InfoSystem::InfoCustomDataHash >() || !m_scrobbler )
|
||||||
|
{
|
||||||
|
dataError( caller, type, data, customData );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
InfoCustomDataHash hash = data.value< Tomahawk::InfoSystem::InfoCustomDataHash >();
|
||||||
|
if ( !hash.contains( "title" ) || !hash.contains( "artist" ) || !hash.contains( "album" ) || !hash.contains( "duration" ) )
|
||||||
|
{
|
||||||
|
dataError( caller, type, data, customData );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_track = lastfm::MutableTrack();
|
||||||
|
m_track.stamp();
|
||||||
|
|
||||||
|
m_track.setTitle( hash["title"].toString() );
|
||||||
|
m_track.setArtist( hash["artist"].toString() );
|
||||||
|
m_track.setAlbum( hash["album"].toString() );
|
||||||
|
m_track.setDuration( hash["duration"].toUInt() );
|
||||||
|
m_track.setSource( lastfm::Track::Player );
|
||||||
|
|
||||||
|
m_scrobbler->nowPlaying( m_track );
|
||||||
|
emit info( caller, type, data, QVariant(), customData );
|
||||||
|
emit finished( caller, type );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LastFmPlugin::dataError( const QString &caller, const InfoType type, const QVariant& data, Tomahawk::InfoSystem::InfoCustomDataHash &customData )
|
||||||
|
{
|
||||||
|
emit info( caller, type, data, QVariant(), customData );
|
||||||
|
emit finished( caller, type );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LastFmPlugin::scrobble( const QString &caller, const InfoType type, const QVariant& data, Tomahawk::InfoSystem::InfoCustomDataHash &customData )
|
||||||
|
{
|
||||||
|
Q_ASSERT( QThread::currentThread() == thread() );
|
||||||
|
|
||||||
|
if ( !m_scrobbler || m_track.isNull() )
|
||||||
|
{
|
||||||
|
dataError( caller, type, data, customData );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << Q_FUNC_INFO << m_track.toString();
|
||||||
|
m_scrobbler->cache( m_track );
|
||||||
|
m_scrobbler->submit();
|
||||||
|
|
||||||
|
emit info( caller, type, data, QVariant(), customData );
|
||||||
|
emit finished( caller, type );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
LastFmPlugin::settingsChanged()
|
||||||
|
{
|
||||||
|
if( !m_scrobbler && TomahawkSettings::instance()->scrobblingEnabled() )
|
||||||
|
{ // can simply create the scrobbler
|
||||||
|
lastfm::ws::Username = TomahawkSettings::instance()->lastFmUsername();
|
||||||
|
m_pw = TomahawkSettings::instance()->lastFmPassword();
|
||||||
|
|
||||||
|
createScrobbler();
|
||||||
|
}
|
||||||
|
else if( m_scrobbler && !TomahawkSettings::instance()->scrobblingEnabled() )
|
||||||
|
{
|
||||||
|
delete m_scrobbler;
|
||||||
|
m_scrobbler = 0;
|
||||||
|
}
|
||||||
|
else if( TomahawkSettings::instance()->lastFmUsername() != lastfm::ws::Username ||
|
||||||
|
TomahawkSettings::instance()->lastFmPassword() != m_pw )
|
||||||
|
{
|
||||||
|
lastfm::ws::Username = TomahawkSettings::instance()->lastFmUsername();
|
||||||
|
// credentials have changed, have to re-create scrobbler for them to take effect
|
||||||
|
if( m_scrobbler )
|
||||||
|
delete m_scrobbler;
|
||||||
|
|
||||||
|
createScrobbler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
LastFmPlugin::onAuthenticated()
|
||||||
|
{
|
||||||
|
if( !m_authJob )
|
||||||
|
{
|
||||||
|
qDebug() << Q_FUNC_INFO << "Help! No longer got a last.fm auth job!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_authJob->error() == QNetworkReply::NoError )
|
||||||
|
{
|
||||||
|
lastfm::XmlQuery lfm = lastfm::XmlQuery( m_authJob->readAll() );
|
||||||
|
|
||||||
|
if( lfm.children( "error" ).size() > 0 )
|
||||||
|
{
|
||||||
|
qDebug() << "Error from authenticating with Last.fm service:" << lfm.text();
|
||||||
|
TomahawkSettings::instance()->setLastFmSessionKey( QByteArray() );
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lastfm::ws::SessionKey = lfm[ "session" ][ "key" ].text();
|
||||||
|
|
||||||
|
TomahawkSettings::instance()->setLastFmSessionKey( lastfm::ws::SessionKey.toLatin1() );
|
||||||
|
|
||||||
|
if( TomahawkSettings::instance()->scrobblingEnabled() )
|
||||||
|
m_scrobbler = new lastfm::Audioscrobbler( "thk" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qDebug() << "Got error in Last.fm authentication job:" << m_authJob->errorString();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_authJob->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
LastFmPlugin::createScrobbler()
|
||||||
|
{
|
||||||
|
if( TomahawkSettings::instance()->lastFmSessionKey().isEmpty() ) // no session key, so get one
|
||||||
|
{
|
||||||
|
QString authToken = md5( ( lastfm::ws::Username.toLower() + md5( m_pw.toUtf8() ) ).toUtf8() );
|
||||||
|
|
||||||
|
QMap<QString, QString> query;
|
||||||
|
query[ "method" ] = "auth.getMobileSession";
|
||||||
|
query[ "username" ] = lastfm::ws::Username;
|
||||||
|
query[ "authToken" ] = authToken;
|
||||||
|
m_authJob = lastfm::ws::post( query );
|
||||||
|
|
||||||
|
connect( m_authJob, SIGNAL( finished() ), SLOT( onAuthenticated() ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lastfm::ws::SessionKey = TomahawkSettings::instance()->lastFmSessionKey();
|
||||||
|
|
||||||
|
m_scrobbler = new lastfm::Audioscrobbler( "thk" );
|
||||||
|
m_scrobbler->moveToThread( thread() );
|
||||||
|
}
|
||||||
|
}
|
69
src/infosystem/infoplugins/lastfmplugin.h
Normal file
69
src/infosystem/infoplugins/lastfmplugin.h
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||||
|
*
|
||||||
|
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LASTFMPLUGIN_H
|
||||||
|
#define LASTFMPLUGIN_H
|
||||||
|
#include "tomahawk/infosystem.h"
|
||||||
|
#include "result.h"
|
||||||
|
|
||||||
|
#include <lastfm/Track>
|
||||||
|
#include <lastfm/Audioscrobbler>
|
||||||
|
#include <lastfm/ScrobblePoint>
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class QNetworkReply;
|
||||||
|
|
||||||
|
namespace Tomahawk
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace InfoSystem
|
||||||
|
{
|
||||||
|
|
||||||
|
class LastFmPlugin : public InfoPlugin
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
LastFmPlugin( QObject *parent );
|
||||||
|
virtual ~LastFmPlugin();
|
||||||
|
|
||||||
|
void getInfo( const QString &caller, const InfoType type, const QVariant &data, InfoCustomDataHash customData );
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void settingsChanged();
|
||||||
|
void onAuthenticated();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void scrobble( const QString &caller, const InfoType type, const QVariant& data, InfoCustomDataHash &customData );
|
||||||
|
void createScrobbler();
|
||||||
|
void nowPlaying( const QString &caller, const InfoType type, const QVariant& data, InfoCustomDataHash &customData );
|
||||||
|
void dataError( const QString &caller, const InfoType type, const QVariant& data, InfoCustomDataHash &customData );
|
||||||
|
|
||||||
|
lastfm::MutableTrack m_track;
|
||||||
|
lastfm::Audioscrobbler* m_scrobbler;
|
||||||
|
QString m_pw;
|
||||||
|
|
||||||
|
QNetworkReply* m_authJob;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // LASTFMPLUGIN_H
|
@@ -19,6 +19,7 @@
|
|||||||
#include "tomahawk/infosystem.h"
|
#include "tomahawk/infosystem.h"
|
||||||
#include "infoplugins/echonestplugin.h"
|
#include "infoplugins/echonestplugin.h"
|
||||||
#include "infoplugins/musixmatchplugin.h"
|
#include "infoplugins/musixmatchplugin.h"
|
||||||
|
#include "infoplugins/lastfmplugin.h"
|
||||||
|
|
||||||
using namespace Tomahawk::InfoSystem;
|
using namespace Tomahawk::InfoSystem;
|
||||||
|
|
||||||
@@ -33,6 +34,8 @@ InfoSystem::InfoSystem(QObject *parent)
|
|||||||
m_plugins.append(enptr);
|
m_plugins.append(enptr);
|
||||||
InfoPluginPtr mmptr(new MusixMatchPlugin(this));
|
InfoPluginPtr mmptr(new MusixMatchPlugin(this));
|
||||||
m_plugins.append(mmptr);
|
m_plugins.append(mmptr);
|
||||||
|
InfoPluginPtr lfmptr(new LastFmPlugin(this));
|
||||||
|
m_plugins.append(lfmptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InfoSystem::registerInfoTypes(const InfoPluginPtr &plugin, const QSet< InfoType >& types)
|
void InfoSystem::registerInfoTypes(const InfoPluginPtr &plugin, const QSet< InfoType >& types)
|
||||||
|
@@ -27,67 +27,27 @@
|
|||||||
#include "audio/audioengine.h"
|
#include "audio/audioengine.h"
|
||||||
#include "tomahawksettings.h"
|
#include "tomahawksettings.h"
|
||||||
#include "tomahawk/tomahawkapp.h"
|
#include "tomahawk/tomahawkapp.h"
|
||||||
|
#include "tomahawk/infosystem.h"
|
||||||
|
|
||||||
#include <lastfm/ws.h>
|
static QString s_infoIdentifier = QString("SCROBBLER");
|
||||||
#include <lastfm/XmlQuery>
|
|
||||||
|
|
||||||
|
|
||||||
static QString
|
|
||||||
md5( const QByteArray& src )
|
|
||||||
{
|
|
||||||
QByteArray const digest = QCryptographicHash::hash( src, QCryptographicHash::Md5 );
|
|
||||||
return QString::fromLatin1( digest.toHex() ).rightJustified( 32, '0' );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Scrobbler::Scrobbler( QObject* parent )
|
Scrobbler::Scrobbler( QObject* parent )
|
||||||
: QObject( parent )
|
: QObject( parent )
|
||||||
, m_scrobbler( 0 )
|
|
||||||
, m_reachedScrobblePoint( false )
|
, m_reachedScrobblePoint( false )
|
||||||
, m_authJob( 0 )
|
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
Your API Key is 7194b85b6d1f424fe1668173a78c0c4a
|
|
||||||
Your secret is ba80f1df6d27ae63e9cb1d33ccf2052f
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Flush session key cache
|
|
||||||
TomahawkSettings::instance()->setLastFmSessionKey( QByteArray() );
|
|
||||||
|
|
||||||
lastfm::ws::ApiKey = "7194b85b6d1f424fe1668173a78c0c4a";
|
|
||||||
lastfm::ws::SharedSecret = "ba80f1df6d27ae63e9cb1d33ccf2052f";
|
|
||||||
lastfm::ws::Username = TomahawkSettings::instance()->lastFmUsername();
|
|
||||||
|
|
||||||
m_pw = TomahawkSettings::instance()->lastFmPassword();
|
|
||||||
|
|
||||||
if( TomahawkSettings::instance()->scrobblingEnabled() && !lastfm::ws::Username.isEmpty() )
|
|
||||||
{
|
|
||||||
createScrobbler();
|
|
||||||
}
|
|
||||||
|
|
||||||
//HACK work around a bug in liblastfm---it doesn't create its config dir, so when it
|
|
||||||
// tries to write the track cache, it fails silently. until we have a fixed version, do this
|
|
||||||
// code taken from Amarok (src/services/lastfm/ScrobblerAdapter.cpp)
|
|
||||||
#ifdef Q_WS_X11
|
|
||||||
QString lpath = QDir::home().filePath( ".local/share/Last.fm" );
|
|
||||||
QDir ldir = QDir( lpath );
|
|
||||||
if( !ldir.exists() )
|
|
||||||
{
|
|
||||||
ldir.mkpath( lpath );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
connect( TomahawkSettings::instance(), SIGNAL( changed() ),
|
|
||||||
SLOT( settingsChanged() ), Qt::QueuedConnection );
|
|
||||||
|
|
||||||
connect( AudioEngine::instance(), SIGNAL( timerSeconds( unsigned int ) ),
|
connect( AudioEngine::instance(), SIGNAL( timerSeconds( unsigned int ) ),
|
||||||
SLOT( engineTick( unsigned int ) ), Qt::QueuedConnection );
|
SLOT( engineTick( unsigned int ) ), Qt::QueuedConnection );
|
||||||
|
|
||||||
|
connect( TomahawkApp::instance()->infoSystem(),
|
||||||
|
SIGNAL( info( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomDataHash ) ),
|
||||||
|
SLOT( infoSystemInfo( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomDataHash ) ) );
|
||||||
|
|
||||||
|
connect( TomahawkApp::instance()->infoSystem(), SIGNAL( finished( QString ) ), SLOT( infoSystemFinished( QString ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Scrobbler::~Scrobbler()
|
Scrobbler::~Scrobbler()
|
||||||
{
|
{
|
||||||
delete m_scrobbler;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -97,26 +57,23 @@ Scrobbler::trackStarted( const Tomahawk::result_ptr& track )
|
|||||||
Q_ASSERT( QThread::currentThread() == thread() );
|
Q_ASSERT( QThread::currentThread() == thread() );
|
||||||
// qDebug() << Q_FUNC_INFO;
|
// qDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
if( !m_scrobbler )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if( m_reachedScrobblePoint )
|
if( m_reachedScrobblePoint )
|
||||||
{
|
{
|
||||||
m_reachedScrobblePoint = false;
|
m_reachedScrobblePoint = false;
|
||||||
scrobble();
|
scrobble();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_track = lastfm::MutableTrack();
|
Tomahawk::InfoSystem::InfoCustomDataHash trackInfo;
|
||||||
m_track.stamp();
|
|
||||||
|
trackInfo["title"] = QVariant::fromValue< QString >( track->track() );
|
||||||
m_track.setTitle( track->track() );
|
trackInfo["artist"] = QVariant::fromValue< QString >( track->artist()->name() );
|
||||||
m_track.setArtist( track->artist()->name() );
|
trackInfo["album"] = QVariant::fromValue< QString >( track->album()->name() );
|
||||||
m_track.setAlbum( track->album()->name() );
|
trackInfo["duration"] = QVariant::fromValue< uint >( track->duration() );
|
||||||
m_track.setDuration( track->duration() );
|
TomahawkApp::instance()->infoSystem()->getInfo(
|
||||||
m_track.setSource( lastfm::Track::Player );
|
s_infoIdentifier, Tomahawk::InfoSystem::InfoMiscSubmitNowPlaying,
|
||||||
|
QVariant::fromValue< Tomahawk::InfoSystem::InfoCustomDataHash >( trackInfo ), Tomahawk::InfoSystem::InfoCustomDataHash() );
|
||||||
m_scrobbler->nowPlaying( m_track );
|
|
||||||
m_scrobblePoint = ScrobblePoint( m_track.duration() / 2 );
|
m_scrobblePoint = ScrobblePoint( track->duration() / 2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -159,102 +116,31 @@ void
|
|||||||
Scrobbler::scrobble()
|
Scrobbler::scrobble()
|
||||||
{
|
{
|
||||||
Q_ASSERT( QThread::currentThread() == thread() );
|
Q_ASSERT( QThread::currentThread() == thread() );
|
||||||
|
|
||||||
if ( !m_scrobbler || m_track.isNull() )
|
|
||||||
return;
|
|
||||||
|
|
||||||
qDebug() << Q_FUNC_INFO << m_track.toString();
|
|
||||||
m_scrobbler->cache( m_track );
|
|
||||||
m_scrobbler->submit();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Scrobbler::settingsChanged()
|
|
||||||
{
|
|
||||||
if( !m_scrobbler && TomahawkSettings::instance()->scrobblingEnabled() )
|
|
||||||
{ // can simply create the scrobbler
|
|
||||||
lastfm::ws::Username = TomahawkSettings::instance()->lastFmUsername();
|
|
||||||
m_pw = TomahawkSettings::instance()->lastFmPassword();
|
|
||||||
|
|
||||||
createScrobbler();
|
|
||||||
}
|
|
||||||
else if( m_scrobbler && !TomahawkSettings::instance()->scrobblingEnabled() )
|
|
||||||
{
|
|
||||||
delete m_scrobbler;
|
|
||||||
m_scrobbler = 0;
|
|
||||||
}
|
|
||||||
else if( TomahawkSettings::instance()->lastFmUsername() != lastfm::ws::Username ||
|
|
||||||
TomahawkSettings::instance()->lastFmPassword() != m_pw )
|
|
||||||
{
|
|
||||||
lastfm::ws::Username = TomahawkSettings::instance()->lastFmUsername();
|
|
||||||
// credentials have changed, have to re-create scrobbler for them to take effect
|
|
||||||
if( m_scrobbler )
|
|
||||||
delete m_scrobbler;
|
|
||||||
|
|
||||||
createScrobbler();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Scrobbler::onAuthenticated()
|
|
||||||
{
|
|
||||||
if( !m_authJob )
|
|
||||||
{
|
|
||||||
qDebug() << Q_FUNC_INFO << "Help! No longer got a last.fm auth job!";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( m_authJob->error() == QNetworkReply::NoError )
|
TomahawkApp::instance()->infoSystem()->getInfo(
|
||||||
{
|
s_infoIdentifier, Tomahawk::InfoSystem::InfoMiscSubmitScrobble,
|
||||||
lastfm::XmlQuery lfm = lastfm::XmlQuery( m_authJob->readAll() );
|
QVariant(), Tomahawk::InfoSystem::InfoCustomDataHash() );
|
||||||
|
|
||||||
if( lfm.children( "error" ).size() > 0 )
|
|
||||||
{
|
|
||||||
qDebug() << "Error from authenticating with Last.fm service:" << lfm.text();
|
|
||||||
TomahawkSettings::instance()->setLastFmSessionKey( QByteArray() );
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lastfm::ws::SessionKey = lfm[ "session" ][ "key" ].text();
|
|
||||||
|
|
||||||
TomahawkSettings::instance()->setLastFmSessionKey( lastfm::ws::SessionKey.toLatin1() );
|
|
||||||
|
|
||||||
if( TomahawkSettings::instance()->scrobblingEnabled() )
|
|
||||||
m_scrobbler = new lastfm::Audioscrobbler( "thk" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
qDebug() << "Got error in Last.fm authentication job:" << m_authJob->errorString();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_authJob->deleteLater();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Scrobbler::createScrobbler()
|
Scrobbler::infoSystemInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input, QVariant output, Tomahawk::InfoSystem::InfoCustomDataHash customData )
|
||||||
{
|
{
|
||||||
if( TomahawkSettings::instance()->lastFmSessionKey().isEmpty() ) // no session key, so get one
|
if ( caller == s_infoIdentifier )
|
||||||
{
|
{
|
||||||
QString authToken = md5( ( lastfm::ws::Username.toLower() + md5( m_pw.toUtf8() ) ).toUtf8() );
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
if ( type == Tomahawk::InfoSystem::InfoMiscSubmitNowPlaying )
|
||||||
QMap<QString, QString> query;
|
qDebug() << "Scrobbler received now playing response from InfoSystem";
|
||||||
query[ "method" ] = "auth.getMobileSession";
|
else if ( type == Tomahawk::InfoSystem::InfoMiscSubmitScrobble )
|
||||||
query[ "username" ] = lastfm::ws::Username;
|
qDebug() << "Scrobbler received scrobble response from InfoSystem";
|
||||||
query[ "authToken" ] = authToken;
|
|
||||||
m_authJob = lastfm::ws::post( query );
|
|
||||||
|
|
||||||
connect( m_authJob, SIGNAL( finished() ), SLOT( onAuthenticated() ) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lastfm::ws::SessionKey = TomahawkSettings::instance()->lastFmSessionKey();
|
|
||||||
|
|
||||||
m_scrobbler = new lastfm::Audioscrobbler( "thk" );
|
|
||||||
m_scrobbler->moveToThread( thread() );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Scrobbler::infoSystemFinished( QString target )
|
||||||
|
{
|
||||||
|
if ( target == s_infoIdentifier )
|
||||||
|
{
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
qDebug() << "Scrobbler received done signal from InfoSystem";
|
||||||
|
}
|
||||||
|
}
|
@@ -21,13 +21,12 @@
|
|||||||
|
|
||||||
#include "result.h"
|
#include "result.h"
|
||||||
|
|
||||||
#include <lastfm/Track>
|
#include "lastfm/ScrobblePoint"
|
||||||
#include <lastfm/Audioscrobbler>
|
|
||||||
#include <lastfm/ScrobblePoint>
|
#include "tomahawk/infosystem.h"
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
class QNetworkReply;
|
|
||||||
/**
|
/**
|
||||||
* Simple class that listens to signals from AudioEngine and scrobbles
|
* Simple class that listens to signals from AudioEngine and scrobbles
|
||||||
* what it is playing.
|
* what it is playing.
|
||||||
@@ -46,20 +45,14 @@ public slots:
|
|||||||
void trackStopped();
|
void trackStopped();
|
||||||
void engineTick( unsigned int secondsElapsed );
|
void engineTick( unsigned int secondsElapsed );
|
||||||
|
|
||||||
void settingsChanged();
|
void infoSystemInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input, QVariant output, Tomahawk::InfoSystem::InfoCustomDataHash customData );
|
||||||
void onAuthenticated();
|
void infoSystemFinished( QString target );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void scrobble();
|
void scrobble();
|
||||||
void createScrobbler();
|
|
||||||
|
|
||||||
lastfm::MutableTrack m_track;
|
|
||||||
lastfm::Audioscrobbler* m_scrobbler;
|
|
||||||
QString m_pw;
|
|
||||||
bool m_reachedScrobblePoint;
|
bool m_reachedScrobblePoint;
|
||||||
ScrobblePoint m_scrobblePoint;
|
ScrobblePoint m_scrobblePoint;
|
||||||
|
|
||||||
QNetworkReply* m_authJob;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -213,6 +213,9 @@ TomahawkApp::TomahawkApp( int& argc, char *argv[] )
|
|||||||
connect( m_shortcutHandler, SIGNAL( mute() ), m_audioEngine, SLOT( mute() ) );
|
connect( m_shortcutHandler, SIGNAL( mute() ), m_audioEngine, SLOT( mute() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qDebug() << "Init InfoSystem.";
|
||||||
|
m_infoSystem = new Tomahawk::InfoSystem::InfoSystem( this );
|
||||||
|
|
||||||
#ifdef LIBLASTFM_FOUND
|
#ifdef LIBLASTFM_FOUND
|
||||||
qDebug() << "Init Scrobbler.";
|
qDebug() << "Init Scrobbler.";
|
||||||
m_scrobbler = new Scrobbler( this );
|
m_scrobbler = new Scrobbler( this );
|
||||||
@@ -236,6 +239,7 @@ TomahawkApp::TomahawkApp( int& argc, char *argv[] )
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Set up proxy
|
// Set up proxy
|
||||||
|
//FIXME: This overrides the lastfm proxy above?
|
||||||
if( TomahawkSettings::instance()->proxyType() != QNetworkProxy::NoProxy &&
|
if( TomahawkSettings::instance()->proxyType() != QNetworkProxy::NoProxy &&
|
||||||
!TomahawkSettings::instance()->proxyHost().isEmpty() )
|
!TomahawkSettings::instance()->proxyHost().isEmpty() )
|
||||||
{
|
{
|
||||||
@@ -252,8 +256,6 @@ TomahawkApp::TomahawkApp( int& argc, char *argv[] )
|
|||||||
|
|
||||||
qDebug() << "Init SIP system.";
|
qDebug() << "Init SIP system.";
|
||||||
m_sipHandler = new SipHandler( this );
|
m_sipHandler = new SipHandler( this );
|
||||||
qDebug() << "Init InfoSystem.";
|
|
||||||
m_infoSystem = new Tomahawk::InfoSystem::InfoSystem( this );
|
|
||||||
|
|
||||||
#ifndef TOMAHAWK_HEADLESS
|
#ifndef TOMAHAWK_HEADLESS
|
||||||
if ( !m_headless )
|
if ( !m_headless )
|
||||||
|
Reference in New Issue
Block a user