1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-03-20 15:59:42 +01:00

Add keep-in-synch support to EchonestCatalogSynchronizer

be extra safe
This commit is contained in:
Leo Franchi 2011-09-30 14:45:55 -04:00
parent 1e6bbba189
commit 5f9c21120d
17 changed files with 490 additions and 36 deletions

View File

@ -99,6 +99,8 @@ set( libSources
database/databasecommand_genericselect.cpp
database/databasecommand_setcollectionattributes.cpp
database/databasecommand_collectionattributes.cpp
database/databasecommand_trackattributes.cpp
database/databasecommand_settrackattributes.cpp
database/database.cpp
infobar/infobar.cpp
@ -322,6 +324,8 @@ set( libHeaders
database/databasecommand_genericselect.h
database/databasecommand_setcollectionattributes.h
database/databasecommand_collectionattributes.h
database/databasecommand_trackattributes.h
database/databasecommand_settrackattributes.h
infobar/infobar.h

View File

@ -18,14 +18,18 @@
#include "EchonestCatalogSynchronizer.h"
#include "collection.h"
#include "database/database.h"
#include "database/databasecommand_genericselect.h"
#include "database/databasecommand_setcollectionattributes.h"
#include "tomahawksettings.h"
#include "sourcelist.h"
#include "query.h"
#include <echonest/CatalogUpdateEntry.h>
#include <echonest/Config.h>
#include "database/databasecommand_settrackattributes.h"
#include "database/databasecommand_trackattributes.h"
using namespace Tomahawk;
@ -39,6 +43,8 @@ EchonestCatalogSynchronizer::EchonestCatalogSynchronizer( QObject *parent )
qRegisterMetaType<QList<QStringList> >("QList<QStringList>");
connect( TomahawkSettings::instance(), SIGNAL( changed() ), this, SLOT( checkSettingsChanged() ) );
connect( SourceList::instance()->getLocal()->collection().data(), SIGNAL( tracksAdded( QList<Tomahawk::query_ptr> ) ), this, SLOT( tracksAdded( QList<Tomahawk::query_ptr> ) ), Qt::QueuedConnection );
connect( SourceList::instance()->getLocal()->collection().data(), SIGNAL( tracksRemoved( QList<Tomahawk::query_ptr> ) ), this, SLOT( tracksRemoved( QList<Tomahawk::query_ptr> ) ), Qt::QueuedConnection );
const QByteArray artist = TomahawkSettings::instance()->value( "collection/artistCatalog" ).toByteArray();
const QByteArray song = TomahawkSettings::instance()->value( "collection/songCatalog" ).toByteArray();
@ -46,6 +52,21 @@ EchonestCatalogSynchronizer::EchonestCatalogSynchronizer( QObject *parent )
m_artistCatalog.setId( artist );
if ( !song.isEmpty() )
m_songCatalog.setId( song );
// Sanity check
if ( !m_songCatalog.id().isEmpty() && !m_syncing )
{
// Not syncing but have a catalog id... lets fix this
QNetworkReply* r = m_songCatalog.deleteCatalog();
connect( r, SIGNAL( finished() ), this, SLOT( catalogDeleted() ) );
r->setProperty( "type", "song" );
}
if ( !m_artistCatalog.id().isEmpty() && !m_syncing )
{
QNetworkReply* r = m_artistCatalog.deleteCatalog();
connect( r, SIGNAL( finished() ), this, SLOT( catalogDeleted() ) );
r->setProperty( "type", "artist" );
}
}
void
@ -60,12 +81,52 @@ EchonestCatalogSynchronizer::checkSettingsChanged()
uploadDb();
} else if ( !TomahawkSettings::instance()->enableEchonestCatalogs() && m_syncing )
{
m_songCatalog.deleteCatalog();
m_artistCatalog.deleteCatalog();
// delete all track nums and catalog ids from our peers
{
DatabaseCommand_SetTrackAttributes* cmd = new DatabaseCommand_SetTrackAttributes( DatabaseCommand_SetTrackAttributes::EchonestCatalogId );
Database::instance()->enqueue( QSharedPointer< DatabaseCommand >( cmd ) );
}
{
DatabaseCommand_SetCollectionAttributes* cmd = new DatabaseCommand_SetCollectionAttributes( DatabaseCommand_SetCollectionAttributes::EchonestSongCatalog, true );
Database::instance()->enqueue( QSharedPointer< DatabaseCommand >( cmd ) );
}
if ( !m_songCatalog.id().isEmpty() )
{
QNetworkReply* r = m_songCatalog.deleteCatalog();
connect( r, SIGNAL( finished() ), this, SLOT( catalogDeleted() ) );
r->setProperty( "type", "song" );
}
if ( !m_artistCatalog.id().isEmpty() )
{
QNetworkReply* r = m_artistCatalog.deleteCatalog();
connect( r, SIGNAL( finished() ), this, SLOT( catalogDeleted() ) );
r->setProperty( "type", "artist" );
}
m_syncing = false;
}
}
void
EchonestCatalogSynchronizer::catalogDeleted()
{
QNetworkReply* r = qobject_cast< QNetworkReply* >( sender() );
Q_ASSERT( r );
QString toDel = QString( "collection/%1Catalog" ).arg( r->property( "type" ).toString() );
try
{
// HACK libechonest bug, should be a static method but it's not. Doesn't actually use any instance vars though
m_songCatalog.parseDelete( r );
// If we didn't throw, no errors, so clear our config
TomahawkSettings::instance()->setValue( toDel, QString() );
} catch ( const Echonest::ParseError& e )
{}
}
void
EchonestCatalogSynchronizer::uploadDb()
{
@ -73,8 +134,8 @@ EchonestCatalogSynchronizer::uploadDb()
QNetworkReply* r = Echonest::Catalog::create( QString( "%1_song" ).arg( Database::instance()->dbid() ), Echonest::CatalogTypes::Song );
connect( r, SIGNAL( finished() ), this, SLOT( songCreateFinished() ) );
r = Echonest::Catalog::create( QString( "%1_artist" ).arg( Database::instance()->dbid() ), Echonest::CatalogTypes::Artist );
connect( r, SIGNAL( finished() ), this, SLOT( artistCreateFinished() ) );
// r = Echonest::Catalog::create( QString( "%1_artist" ).arg( Database::instance()->dbid() ), Echonest::CatalogTypes::Artist );
// connect( r, SIGNAL( finished() ), this, SLOT( artistCreateFinished() ) );
}
void
@ -88,9 +149,8 @@ EchonestCatalogSynchronizer::songCreateFinished()
{
m_songCatalog = Echonest::Catalog::parseCreate( r );
TomahawkSettings::instance()->setValue( "collection/songCatalog", m_songCatalog.id() );
QSharedPointer< DatabaseCommand > cmd( new DatabaseCommand_SetCollectionAttributes( SourceList::instance()->getLocal(),
DatabaseCommand_SetCollectionAttributes::EchonestSongCatalog,
m_songCatalog.id() ) );
QSharedPointer< DatabaseCommand > cmd( new DatabaseCommand_SetCollectionAttributes( DatabaseCommand_SetCollectionAttributes::EchonestSongCatalog,
m_songCatalog.id() ) );
Database::instance()->enqueue( cmd );
} catch ( const Echonest::ParseError& e )
{
@ -98,7 +158,7 @@ EchonestCatalogSynchronizer::songCreateFinished()
return;
}
QString sql( "SELECT track.name, artist.name, album.name "
QString sql( "SELECT track.id, track.name, artist.name, album.name "
"FROM file, artist, track, file_join "
"LEFT OUTER JOIN album "
"ON file_join.album = album.id "
@ -107,7 +167,7 @@ EchonestCatalogSynchronizer::songCreateFinished()
"AND file_join.track = track.id "
"AND file.source IS NULL");
DatabaseCommand_GenericSelect* cmd = new DatabaseCommand_GenericSelect( sql, DatabaseCommand_GenericSelect::Track, true );
connect( cmd, SIGNAL( rawData( QList< QStringList > ) ), this, SLOT( rawTracks( QList< QStringList > ) ) );
connect( cmd, SIGNAL( rawData( QList< QStringList > ) ), this, SLOT( rawTracksAdd( QList< QStringList > ) ) );
Database::instance()->enqueue( QSharedPointer< DatabaseCommand >( cmd ) );
}
@ -138,7 +198,7 @@ EchonestCatalogSynchronizer::artistCreateFinished()
}
void
EchonestCatalogSynchronizer::rawTracks( const QList< QStringList >& tracks )
EchonestCatalogSynchronizer::rawTracksAdd( const QList< QStringList >& tracks )
{
tDebug() << "Got raw tracks, num:" << tracks.size();
@ -151,14 +211,18 @@ EchonestCatalogSynchronizer::rawTracks( const QList< QStringList >& tracks )
cur = ( cur + 2000 > tracks.size() ) ? tracks.size() : cur + 2000;
tDebug() << "Enqueueing a batch of tracks to upload to echonest catalog:" << cur - prev;
Echonest::CatalogUpdateEntries entries( cur - prev );
Echonest::CatalogUpdateEntries entries;
QList< QPair< QID, QString > > inserted;
for ( int i = prev; i < cur; i++ )
{
if ( tracks[i][0].isEmpty() || tracks[i][1].isEmpty() )
if ( tracks[i][1].isEmpty() || tracks[i][2].isEmpty() )
continue;
entries.append( entryFromTrack( tracks[i] ) );
entries.append( entryFromTrack( tracks[i], Echonest::CatalogTypes::Update ) );
inserted << QPair< QID, QString >( tracks[i][0], entries.last().itemId() );
}
tDebug() << "Done queuing:" << entries.size() << "tracks";
m_queuedUpdates.enqueue( entries );
m_queuedTrackInfo.enqueue( inserted );
}
doUploadJob();
@ -172,6 +236,7 @@ EchonestCatalogSynchronizer::doUploadJob()
return;
Echonest::CatalogUpdateEntries entries = m_queuedUpdates.dequeue();
tDebug() << "Updating number of entries:" << entries.count();
QNetworkReply* updateJob = m_songCatalog.update( entries );
connect( updateJob, SIGNAL( finished() ), this, SLOT( songUpdateFinished() ) );
@ -179,14 +244,14 @@ EchonestCatalogSynchronizer::doUploadJob()
Echonest::CatalogUpdateEntry
EchonestCatalogSynchronizer::entryFromTrack( const QStringList& track ) const
EchonestCatalogSynchronizer::entryFromTrack( const QStringList& track, Echonest::CatalogTypes::Action action ) const
{
//qDebug() << "UPLOADING:" << track[0] << track[1] << track[2];
Echonest::CatalogUpdateEntry entry;
entry.setAction( Echonest::CatalogTypes::Update );
entry.setSongName( escape( track[ 0 ] ) );
entry.setArtistName( escape( track[ 1 ] ) );
entry.setRelease( escape( track[ 2 ] ) );
entry.setAction( action );
entry.setSongName( escape( track[ 1 ] ) );
entry.setArtistName( escape( track[ 2 ] ) );
entry.setRelease( escape( track[ 3 ] ) );
entry.setItemId( uuid().toUtf8() );
return entry;
@ -199,7 +264,13 @@ EchonestCatalogSynchronizer::songUpdateFinished()
QNetworkReply* r = qobject_cast< QNetworkReply* >( sender() );
Q_ASSERT( r );
doUploadJob();
QList< QPair< QID, QString > > ids = m_queuedTrackInfo.dequeue();
if ( r->error() == QNetworkReply::NoError )
{
// Save the ids of each track in the echonest catalog to our db, so we can keep track of them
DatabaseCommand_SetTrackAttributes* cmd = new DatabaseCommand_SetTrackAttributes( DatabaseCommand_SetTrackAttributes::EchonestCatalogId, ids );
Database::instance()->enqueue( QSharedPointer< DatabaseCommand >( cmd ) );
}
try
{
@ -209,8 +280,9 @@ EchonestCatalogSynchronizer::songUpdateFinished()
} catch ( const Echonest::ParseError& e )
{
tLog() << "Echonest threw an exception parsing catalog update finished:" << e.what();
return;
}
doUploadJob();
}
void
@ -231,6 +303,69 @@ EchonestCatalogSynchronizer::checkTicket()
}
}
void
EchonestCatalogSynchronizer::tracksAdded( const QList< query_ptr >& tracks )
{
if ( !m_syncing || m_songCatalog.id().isEmpty() || tracks.isEmpty() )
return;
QList< QStringList > rawTracks;
foreach( const query_ptr& track, tracks )
{
// DatabaseCommand_AddFiles sets the track id on the result
int id = -1;
if ( track->results().size() == 1 )
id = track->results().first()->dbid();
else
{
tLog() << Q_FUNC_INFO << "No dbid for track we got in tracksAdded()!";
continue;
}
rawTracks << ( QStringList() << QString::number( id ) << track->track() << track->artist() << track->album() );
}
rawTracksAdd( rawTracks );
}
void
EchonestCatalogSynchronizer::tracksRemoved( const QList< query_ptr >& tracks )
{
if ( !m_syncing || m_songCatalog.id().isEmpty() || tracks.isEmpty() )
return;
// get the catalog ids, if they exist, otherwise we can't do anything with them.
QList< QID > qids;
foreach ( const query_ptr& q, tracks )
{
qids << q->id();
}
DatabaseCommand_TrackAttributes* cmd = new DatabaseCommand_TrackAttributes( DatabaseCommand_SetTrackAttributes::EchonestCatalogId, qids );
connect( cmd, SIGNAL( trackAttributes( PairList ) ), this, SLOT( trackAttributes( PairList ) ) );
Database::instance()->enqueue( QSharedPointer< DatabaseCommand >( cmd ) );
}
void
EchonestCatalogSynchronizer::trackAttributes( PairList attributes )
{
// QString actionStr = cmd->property( "action" ).toString();
Echonest::CatalogTypes::Action action;
// if ( actionStr == "delete" )
action = Echonest::CatalogTypes::Delete;
Echonest::CatalogUpdateEntries entries( attributes.size() );
QPair< QID, QString > track;
foreach ( track, attributes )
{
Echonest::CatalogUpdateEntry e( action );
e.setItemId( track.second.toUtf8() );
entries.append( e );
}
m_songCatalog.update( entries );
}
QByteArray
EchonestCatalogSynchronizer::escape( const QString &in ) const
{

View File

@ -20,6 +20,8 @@
#define ECHONESTCATALOGSYNCHRONIZER_H
#include "dllmacro.h"
#include "query.h"
#include "database/databasecommand_trackattributes.h"
#include <echonest/Catalog.h>
@ -51,19 +53,25 @@ signals:
private slots:
void checkSettingsChanged();
void tracksAdded( const QList<Tomahawk::query_ptr>& );
void tracksRemoved( const QList<Tomahawk::query_ptr>& );
// Echonest slots
void songCreateFinished();
void artistCreateFinished();
void songUpdateFinished();
void catalogDeleted();
void checkTicket();
void rawTracks( const QList< QStringList >& tracks );
void rawTracksAdd( const QList< QStringList >& tracks );
void trackAttributes( PairList );
private:
void uploadDb();
QByteArray escape( const QString& in ) const;
Echonest::CatalogUpdateEntry entryFromTrack( const QStringList& ) const;
Echonest::CatalogUpdateEntry entryFromTrack( const QStringList&, Echonest::CatalogTypes::Action action ) const;
void doUploadJob();
bool m_syncing;
@ -72,6 +80,7 @@ private:
Echonest::Catalog m_artistCatalog;
QQueue< Echonest::CatalogUpdateEntries > m_queuedUpdates;
QQueue< QList< QPair< QID, QString > > > m_queuedTrackInfo;
static EchonestCatalogSynchronizer* s_instance;
};

View File

@ -259,6 +259,7 @@ Collection::delTracks( const QStringList& files )
i++;
}
tDebug() << "Emitting tracks removed:" << tracks.size();
emit tracksRemoved( tracks );
}

View File

@ -32,6 +32,7 @@
#include "utils/logger.h"
#include "databasecommand_setcollectionattributes.h"
#include "databasecommand_settrackattributes.h"
DatabaseCommand::DatabaseCommand( QObject* parent )
@ -174,6 +175,13 @@ DatabaseCommand::factory( const QVariant& op, const source_ptr& source )
QJson::QObjectHelper::qvariant2qobject( op.toMap(), cmd );
return cmd;
}
else if( name == "settrackattributes" )
{
DatabaseCommand_SetTrackAttributes * cmd = new DatabaseCommand_SetTrackAttributes;
cmd->setSource( source );
QJson::QObjectHelper::qvariant2qobject( op.toMap(), cmd );
return cmd;
}
qDebug() << "ERROR in" << Q_FUNC_INFO << name;
// Q_ASSERT( false );

View File

@ -24,7 +24,6 @@ DatabaseCommand_CollectionAttributes::DatabaseCommand_CollectionAttributes( Data
: DatabaseCommand()
, m_type( type )
{
qRegisterMetaType< PairList >("PairList");
}
void

View File

@ -16,16 +16,14 @@
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DATABASECOMMAND_ECHONESTCATALOG_H
#define DATABASECOMMAND_ECHONESTCATALOG_H
#ifndef DATABASECOMMAND_COLLECTIONATTRIBUTES_H
#define DATABASECOMMAND_COLLECTIONATTRIBUTES_H
#include "typedefs.h"
#include "databasecommand.h"
#include "databasecommand_setcollectionattributes.h"
#include <QByteArray>
typedef QList< QPair< QString, QString > > PairList;
class DatabaseCommand_CollectionAttributes : public DatabaseCommand
{
Q_OBJECT
@ -35,7 +33,7 @@ public:
virtual void exec( DatabaseImpl* lib );
virtual bool doesMutates() const { return false; }
virtual QString commandname() const { return "setcollectionattributes"; }
virtual QString commandname() const { return "collectionattributes"; }
signals:
void collectionAttributes( PairList );
@ -44,5 +42,4 @@ private:
DatabaseCommand_SetCollectionAttributes::AttributeType m_type;
};
Q_DECLARE_METATYPE(PairList)
#endif

View File

@ -47,6 +47,7 @@ DatabaseCommand_DeleteFiles::postCommitHook()
connect( this, SIGNAL( notify( QStringList ) ),
coll, SLOT( delTracks( QStringList ) ), Qt::QueuedConnection );
tDebug() << "Notifying of deleted tracks:" << m_files.size();
emit notify( m_files );
if( source()->isLocal() )

View File

@ -20,20 +20,33 @@
#include "databaseimpl.h"
#include "source.h"
#include "network/servent.h"
#include "sourcelist.h"
DatabaseCommand_SetCollectionAttributes::DatabaseCommand_SetCollectionAttributes( const Tomahawk::source_ptr& source, AttributeType type, const QByteArray& id )
: DatabaseCommandLoggable( source )
DatabaseCommand_SetCollectionAttributes::DatabaseCommand_SetCollectionAttributes( AttributeType type, const QByteArray& id )
: DatabaseCommandLoggable( )
, m_delete( false )
, m_type( type )
, m_id( id )
{
}
DatabaseCommand_SetCollectionAttributes::DatabaseCommand_SetCollectionAttributes( DatabaseCommand_SetCollectionAttributes::AttributeType type, bool toDelete )
: DatabaseCommandLoggable()
, m_delete( toDelete )
, m_type( type )
{
}
void
DatabaseCommand_SetCollectionAttributes::exec( DatabaseImpl *lib )
{
TomahawkSqlQuery query = lib->newquery();
QString sourceStr;
if ( source().isNull() )
setSource( SourceList::instance()->getLocal() );
if ( source().isNull() || source()->isLocal() )
sourceStr = "NULL";
else
@ -48,6 +61,9 @@ DatabaseCommand_SetCollectionAttributes::exec( DatabaseImpl *lib )
TomahawkSqlQuery delQuery = lib->newquery();
delQuery.exec( QString( "DELETE FROM collection_attributes WHERE id %1" ).arg( source()->isLocal() ? QString("IS NULL") : QString( "= %1" ).arg( source()->id() )));
if ( m_delete )
return;
QString queryStr = QString( "INSERT INTO collection_attributes ( id, k, v ) VALUES( %1, \"%2\", \"%3\" )" ).arg( sourceStr ).arg( typeStr ).arg( QString::fromUtf8( m_id ) );
qDebug() << "Doing query:" << queryStr;
query.exec( queryStr );

View File

@ -16,8 +16,8 @@
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DATABASECOMMAND_SAVEECHONESTCATALOG_H
#define DATABASECOMMAND_SAVEECHONESTCATALOG_H
#ifndef DATABASECOMMAND_SETCOLLECTIONATTRIBUTES
#define DATABASECOMMAND_SETCOLLECTIONATTRIBUTES
#include "typedefs.h"
#include "databasecommandloggable.h"
@ -35,7 +35,10 @@ public:
EchonestArtistCatalog = 1
};
DatabaseCommand_SetCollectionAttributes( const Tomahawk::source_ptr& source, AttributeType type, const QByteArray& id );
DatabaseCommand_SetCollectionAttributes( AttributeType type, const QByteArray& id );
// Delete all attributes for the source+type
DatabaseCommand_SetCollectionAttributes( AttributeType type, bool toDelete );
DatabaseCommand_SetCollectionAttributes() {} // JSON
virtual void exec( DatabaseImpl* lib );
virtual bool doesMutates() const { return true; }
@ -50,8 +53,9 @@ public:
int type() const { return (int)m_type; }
private:
bool m_delete;
AttributeType m_type;
QByteArray m_id;
};
#endif // DATABASECOMMAND_SAVEECHONESTCATALOG_H
#endif // DATABASECOMMAND_SETCOLLECTIONATTRIBUTES

View File

@ -0,0 +1,97 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.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 "databasecommand_settrackattributes.h"
#include "tomahawksqlquery.h"
#include "databaseimpl.h"
using namespace Tomahawk;
DatabaseCommand_SetTrackAttributes::DatabaseCommand_SetTrackAttributes( DatabaseCommand_SetTrackAttributes::AttributeType type, QList< QPair< QID, QString > > ids, bool toDelete )
: DatabaseCommandLoggable()
, m_loggable( false )
, m_delete( toDelete )
, m_type( type )
, m_tracks( ids )
{
}
DatabaseCommand_SetTrackAttributes::DatabaseCommand_SetTrackAttributes( DatabaseCommand_SetTrackAttributes::AttributeType type )
: DatabaseCommandLoggable()
, m_loggable( false )
, m_delete( true )
, m_type( type )
{
}
void
DatabaseCommand_SetTrackAttributes::exec( DatabaseImpl* dbi )
{
TomahawkSqlQuery checkquery = dbi->newquery();
TomahawkSqlQuery delquery = dbi->newquery();
TomahawkSqlQuery insertquery = dbi->newquery();
QString k;
switch ( m_type )
{
case EchonestCatalogId:
k = "echonestcatalogid";
break;
}
if ( m_delete && m_tracks.isEmpty() )
{
//delete all
TomahawkSqlQuery delAll = dbi->newquery();
delAll.prepare( "DELETE FROM track_attributes WHERE k = ?" );
delAll.bindValue( 0, k );
delAll.exec();
return;
}
checkquery.prepare( "SELECT id, sortname FROM track WHERE id = ?" );
delquery.prepare( "DELETE FROM track_attributes WHERE id = ? AND k = ?" );
insertquery.prepare( "INSERT INTO track_attributes ( id, k, v ) VALUES( ?, ?, ? )" );
QPair< QID, QString > track;
foreach ( track, m_tracks )
{
checkquery.bindValue( 0, track.first );
if ( !checkquery.exec() )
{
tLog() << "No track in track table for set track attribute command...aborting:" << track.first;
continue;
}
delquery.bindValue( 0, track.first );
delquery.bindValue( 1, k );
delquery.exec();
if ( m_delete )
continue; // stop at deleting, don't insert
insertquery.bindValue( 0, track.first );
insertquery.bindValue( 1, k );
insertquery.bindValue( 2, track.second );
if ( !insertquery.exec() )
tLog() << "Failed to insert track attribute:" << k << track.first << track.second;
}
}

View File

@ -0,0 +1,57 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.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 DATABASECOMMAND_SETTRACKATTRIBUTES
#define DATABASECOMMAND_SETTRACKATTRIBUTES
#include "typedefs.h"
#include "databasecommandloggable.h"
#include <QByteArray>
class DatabaseCommand_SetTrackAttributes : public DatabaseCommandLoggable
{
Q_OBJECT
public:
enum AttributeType {
EchonestCatalogId = 0,
};
// Takes a list of <track_id, value> pairs. key is always type
DatabaseCommand_SetTrackAttributes( AttributeType type, QList< QPair< Tomahawk::QID, QString > > ids, bool toDelete = false );
// Deletes *all tracks with attribute*
DatabaseCommand_SetTrackAttributes( AttributeType type );
DatabaseCommand_SetTrackAttributes() {} // JSON
virtual void exec( DatabaseImpl* lib );
virtual bool doesMutates() const { return true; }
virtual bool loggable() const { return m_loggable; }
virtual QString commandname() const { return "settrackattributes"; }
void setType( int type ) { m_type = (AttributeType)type; }
int type() const { return (int)m_type; }
private:
bool m_loggable, m_delete;
AttributeType m_type;
QList< QPair< Tomahawk::QID, QString > > m_tracks;
};
#endif // DATABASECOMMAND_SETTRACKATTRIBUTES

View File

@ -0,0 +1,71 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.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 "databasecommand_trackattributes.h"
#include "databaseimpl.h"
using namespace Tomahawk;
DatabaseCommand_TrackAttributes::DatabaseCommand_TrackAttributes( DatabaseCommand_SetTrackAttributes::AttributeType type, const QList< Tomahawk::QID > ids )
: DatabaseCommand()
, m_type( type )
, m_ids( ids )
{
}
DatabaseCommand_TrackAttributes::DatabaseCommand_TrackAttributes( DatabaseCommand_SetTrackAttributes::AttributeType type )
: DatabaseCommand()
, m_type( type )
{
}
void DatabaseCommand_TrackAttributes::exec( DatabaseImpl* lib )
{
TomahawkSqlQuery query = lib->newquery();
QString k;
switch ( m_type )
{
case DatabaseCommand_SetTrackAttributes::EchonestCatalogId:
k = "echonestcatalogid";
break;
}
PairList results;
if ( !m_ids.isEmpty() )
{
foreach ( const QID id, m_ids )
{
query.prepare( "SELECT v FROM track_attributes WHERE id = ? AND k = ?" );
query.bindValue( 0, id );
query.bindValue( 1, k );
if ( query.exec() )
results.append( QPair< QID, QString >( id, query.value( 0 ).toString() ) );
}
} else {
query.prepare( "SELECT id, v FROM track_attributes WHERE k = ?" );
query.bindValue( 0, k );
query.exec();
while ( !query.next() )
{
results.append( QPair< QID, QString >( query.value( 0 ).toString(), query.value( 1 ).toString() ) );
}
}
emit trackAttributes( results );
}

View File

@ -0,0 +1,51 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.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 DATABASECOMMAND_TRACKATTRIBUTES_H
#define DATABASECOMMAND_TRACKATTRIBUTES_H
#include "typedefs.h"
#include "databasecommand.h"
#include "databasecommand_collectionattributes.h"
#include "databasecommand_settrackattributes.h"
#include <QByteArray>
class DatabaseCommand_TrackAttributes : public DatabaseCommand
{
Q_OBJECT
public:
// Get all tracks with this attribute
DatabaseCommand_TrackAttributes( DatabaseCommand_SetTrackAttributes::AttributeType type );
// Get the specific tracks with this attribute
DatabaseCommand_TrackAttributes( DatabaseCommand_SetTrackAttributes::AttributeType type, const QList< Tomahawk::QID > ids );
virtual void exec( DatabaseImpl* lib );
virtual bool doesMutates() const { return false; }
virtual QString commandname() const { return "trackattributes"; }
signals:
void trackAttributes( PairList );
private:
DatabaseCommand_SetTrackAttributes::AttributeType m_type;
QList< Tomahawk::QID > m_ids;
};
#endif

View File

@ -21,6 +21,7 @@
#include <QSharedPointer>
#include <QUuid>
#include <QPair>
//template <typename T> class QSharedPointer;
@ -66,6 +67,7 @@ namespace Tomahawk
typedef int AudioErrorCode;
typedef int AudioState;
typedef QList< QPair< QString, QString > > PairList;
// creates 36char ascii guid without {} around it
inline static QString uuid()

View File

@ -367,6 +367,7 @@ TomahawkApp::registerMetaTypes()
qRegisterMetaType< QMap< QString, plentry_ptr > >("QMap< QString, plentry_ptr >");
qRegisterMetaType< QHash< QString, QMap<quint32, quint16> > >("QHash< QString, QMap<quint32, quint16> >");
qRegisterMetaType< QMap< QString, QMap< unsigned int, unsigned int > > >("QMap< QString, QMap< unsigned int, unsigned int > >");
qRegisterMetaType< PairList >("PairList");
qRegisterMetaType< GeneratorMode>("GeneratorMode");
qRegisterMetaType<Tomahawk::GeneratorMode>("Tomahawk::GeneratorMode");

View File

@ -135,7 +135,8 @@ private:
QxtHttpSessionManager m_session;
};
Q_DECLARE_METATYPE( QPersistentModelIndex );
Q_DECLARE_METATYPE( QPersistentModelIndex )
Q_DECLARE_METATYPE(PairList)
#endif // TOMAHAWKAPP_H