1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-03-21 16:29:43 +01:00

* Allow to locally import Last.fm playback history. Works but needs discussion.

This commit is contained in:
Christian Muehlhaeuser 2012-05-22 10:43:39 +02:00
parent 3f5d219549
commit 2ee66a3cda
5 changed files with 152 additions and 31 deletions

View File

@ -17,15 +17,20 @@
*/
#include "LastFmConfig.h"
#include "ui_LastFmConfig.h"
#include "LastFmAccount.h"
#include <utils/TomahawkUtils.h>
#include "ui_LastFmConfig.h"
#include "database/Database.h"
#include "database/DatabaseCommand_LogPlayback.h"
#include "utils/TomahawkUtils.h"
#include "utils/Logger.h"
#include "lastfm/ws.h"
#include "lastfm/User"
#include "lastfm/XmlQuery"
using namespace Tomahawk::Accounts;
LastFmConfig::LastFmConfig( LastFmAccount* account )
: QWidget( 0 )
, m_account( account )
@ -33,18 +38,17 @@ LastFmConfig::LastFmConfig( LastFmAccount* account )
m_ui = new Ui_LastFmConfig;
m_ui->setupUi( this );
m_ui->progressBar->hide();
m_ui->username->setText( m_account->username() );
m_ui->password->setText( m_account->password() );
m_ui->enable->setChecked( m_account->scrobble() );
connect( m_ui->testLogin, SIGNAL( clicked( bool ) ), this, SLOT( testLogin( bool ) ) );
connect( m_ui->testLogin, SIGNAL( clicked( bool ) ), SLOT( testLogin() ) );
connect( m_ui->importHistory, SIGNAL( clicked( bool ) ), SLOT( loadHistory() ) );
connect( m_ui->username, SIGNAL( textChanged( QString ) ), this, SLOT( enableButton() ) );
connect( m_ui->password, SIGNAL( textChanged( QString ) ), this, SLOT( enableButton() ) );
// #ifdef Q_WS_MAC // FIXME
// m_ui->testLogin->setVisible( false );
// #endif
connect( m_ui->username, SIGNAL( textChanged( QString ) ), SLOT( enableButton() ) );
connect( m_ui->password, SIGNAL( textChanged( QString ) ), SLOT( enableButton() ) );
}
@ -70,10 +74,10 @@ LastFmConfig::username() const
void
LastFmConfig::testLogin(bool )
LastFmConfig::testLogin()
{
m_ui->testLogin->setEnabled( false );
m_ui->testLogin->setText( "Testing..." );
m_ui->testLogin->setText( tr( "Testing..." ) );
QString authToken = TomahawkUtils::md5( ( m_ui->username->text().toLower() + TomahawkUtils::md5( m_ui->password->text().toUtf8() ) ).toUtf8() );
@ -100,6 +104,79 @@ LastFmConfig::enableButton()
}
void
LastFmConfig::loadHistory( int page )
{
if ( page == 1 )
{
m_ui->importHistory->setText( tr( "Importing History..." ) );
m_ui->importHistory->setEnabled( false );
m_ui->progressBar->show();
}
QNetworkReply* reply = lastfm::User( m_ui->username->text().toLower() ).getRecentTracks( 200, page );
connect( reply, SIGNAL( finished() ), SLOT( onHistoryLoaded() ) );
}
void
LastFmConfig::onHistoryLoaded()
{
bool finished = false;
QNetworkReply* reply = qobject_cast< QNetworkReply* >( sender() );
try
{
lastfm::XmlQuery lfm = reply->readAll();
foreach ( lastfm::XmlQuery e, lfm.children( "track" ) )
{
tDebug() << "Found:" << e["artist"].text() << e["name"].text() << e["date"].attribute( "uts" ).toUInt();
Tomahawk::query_ptr query = Query::get( e["artist"].text(), e["name"].text(), QString(), QString(), false );
uint timeStamp = e["date"].attribute( "uts" ).toUInt();
DatabaseCommand_LogPlayback* cmd = new DatabaseCommand_LogPlayback( query, DatabaseCommand_LogPlayback::Finished, timeStamp );
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>(cmd) );
}
if ( !lfm.children( "recenttracks" ).isEmpty() )
{
lastfm::XmlQuery stats = lfm.children( "recenttracks" ).first();
int page = stats.attribute( "page" ).toInt();
int total = stats.attribute( "totalPages" ).toInt();
tDebug() << "page:" << page << "total:" << total;
m_ui->progressBar->setMaximum( total );
m_ui->progressBar->setValue( page );
if ( page < total )
loadHistory( ++page );
else
finished = true;
}
else
finished = true;
}
catch( lastfm::ws::ParseError e )
{
tDebug() << "XmlQuery error:" << e.what();
finished = true;
}
if ( finished )
{
if ( m_ui->progressBar->value() != m_ui->progressBar->maximum() )
m_ui->importHistory->setText( tr( "History Incomplete. Retry" ) );
else
m_ui->importHistory->setText( tr( "Import Playback History" ) );
m_ui->importHistory->setEnabled( true );
}
}
void
LastFmConfig::onLastFmFinished()
{

View File

@ -24,6 +24,7 @@
class Ui_LastFmConfig;
namespace Tomahawk {
namespace Accounts {
class LastFmAccount;
@ -39,11 +40,14 @@ public:
bool scrobble() const;
public slots:
void testLogin( bool );
void testLogin();
void onLastFmFinished();
private slots:
void enableButton();
void loadHistory( int page = 1 );
void onHistoryLoaded();
private:
LastFmAccount* m_account;
@ -51,6 +55,7 @@ private:
};
}
}
#endif // LASTFMCONFIG_H

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>400</width>
<height>220</height>
<height>253</height>
</rect>
</property>
<property name="windowTitle">
@ -77,6 +77,20 @@
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="importHistory">
<property name="text">
<string>Import Playback History</string>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="progressBar">
<property name="value">
<number>0</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>

View File

@ -37,31 +37,33 @@ using namespace Tomahawk;
void
DatabaseCommand_LogPlayback::postCommitHook()
{
if ( !m_query.isNull() )
return;
connect( this, SIGNAL( trackPlaying( Tomahawk::query_ptr, unsigned int ) ),
source().data(), SLOT( onPlaybackStarted( Tomahawk::query_ptr, unsigned int ) ), Qt::QueuedConnection );
connect( this, SIGNAL( trackPlayed( Tomahawk::query_ptr ) ),
source().data(), SLOT( onPlaybackFinished( Tomahawk::query_ptr ) ), Qt::QueuedConnection );
Tomahawk::query_ptr q;
if ( !m_result.isNull() )
if ( !m_result.isNull() && m_query.isNull() )
{
q = m_result->toQuery();
m_query = m_result->toQuery();
}
else
{
// do not auto resolve this track
q = Tomahawk::Query::get( m_artist, m_track, QString() );
m_query = Tomahawk::Query::get( m_artist, m_track, QString() );
}
q->setPlayedBy( source(), m_playtime );
m_query->setPlayedBy( source(), m_playtime );
if ( m_action == Finished )
{
emit trackPlayed( q );
emit trackPlayed( m_query );
}
// if the play time is more than 10 minutes in the past, ignore
else if ( m_action == Started && QDateTime::fromTime_t( playtime() ).secsTo( QDateTime::currentDateTime() ) < STARTED_THRESHOLD )
{
emit trackPlaying( q, m_trackDuration );
emit trackPlaying( m_query, m_trackDuration );
}
if ( source()->isLocal() )
@ -78,25 +80,36 @@ DatabaseCommand_LogPlayback::exec( DatabaseImpl* dbi )
if ( m_action != Finished )
return;
if ( m_secsPlayed < FINISHED_THRESHOLD )
if ( m_secsPlayed < FINISHED_THRESHOLD && m_trackDuration > 0 )
return;
if ( m_artist.isEmpty() || m_track.isEmpty() )
return;
TomahawkSqlQuery query = dbi->newquery();
query.prepare( "INSERT INTO playback_log(source, track, playtime, secs_played) "
"VALUES (?, ?, ?, ?)" );
QVariant srcid = source()->isLocal() ? QVariant( QVariant::Int ) : source()->id();
qDebug() << "Logging playback of" << m_artist << "-" << m_track << "for source" << srcid;
TomahawkSqlQuery query = dbi->newquery();
if ( !m_query.isNull() )
{
query.prepare( QString( "SELECT * FROM playback_log WHERE source %1 AND playtime = %2" ).arg( srcid.isNull() ? "IS NULL" : srcid.toString() ).arg( m_playtime ) );
query.exec();
if ( query.next() )
{
tDebug() << "Ignoring dupe playback log for source" << srcid << "with timestamp" << m_playtime;
return;
}
}
// tDebug() << "Logging playback of" << m_artist << "-" << m_track << "for source" << srcid << "- timestamp:" << m_playtime;
query.prepare( "INSERT INTO playback_log(source, track, playtime, secs_played) VALUES (?, ?, ?, ?)" );
query.bindValue( 0, srcid );
// If there's no artist, becuase it's a resolver result with bad metadata for example, don't save it
bool autoCreate = m_artist.isEmpty();
int artid = dbi->artistId( m_artist, autoCreate );
// If there's no artist, because it's a resolver result with bad metadata for example, don't save it
int artid = dbi->artistId( m_artist, true );
if( artid < 1 )
return;
autoCreate = true; // artistId overwrites autoCreate (reference)
int trkid = dbi->trackId( artid, m_track, autoCreate );
int trkid = dbi->trackId( artid, m_track, true );
if( trkid < 1 )
return;

View File

@ -51,6 +51,17 @@ public:
: DatabaseCommandLoggable( parent ), m_playtime( 0 ), m_secsPlayed( 0 ), m_trackDuration( 0 )
{}
explicit DatabaseCommand_LogPlayback( const Tomahawk::query_ptr& query, Action action, uint timeStamp, QObject* parent = 0 )
: DatabaseCommandLoggable( parent ), m_query( query ), m_secsPlayed( 0 ), m_action( action )
{
m_playtime = timeStamp;
m_trackDuration = 0;
setSource( SourceList::instance()->getLocal() );
setArtist( query->artist() );
setTrack( query->track() );
}
explicit DatabaseCommand_LogPlayback( const Tomahawk::result_ptr& result, Action action, unsigned int secsPlayed = 0, QObject* parent = 0 )
: DatabaseCommandLoggable( parent ), m_result( result ), m_secsPlayed( secsPlayed ), m_action( action )
{
@ -96,6 +107,7 @@ signals:
private:
Tomahawk::result_ptr m_result;
Tomahawk::query_ptr m_query;
QString m_artist;
QString m_track;