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:
parent
3f5d219549
commit
2ee66a3cda
@ -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()
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user