diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt index ef331994b..bb21cf564 100644 --- a/src/libtomahawk/CMakeLists.txt +++ b/src/libtomahawk/CMakeLists.txt @@ -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 diff --git a/src/libtomahawk/EchonestCatalogSynchronizer.cpp b/src/libtomahawk/EchonestCatalogSynchronizer.cpp index e8d001d3f..d21fa915b 100644 --- a/src/libtomahawk/EchonestCatalogSynchronizer.cpp +++ b/src/libtomahawk/EchonestCatalogSynchronizer.cpp @@ -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 #include +#include "database/databasecommand_settrackattributes.h" +#include "database/databasecommand_trackattributes.h" using namespace Tomahawk; @@ -39,6 +43,8 @@ EchonestCatalogSynchronizer::EchonestCatalogSynchronizer( QObject *parent ) qRegisterMetaType >("QList"); connect( TomahawkSettings::instance(), SIGNAL( changed() ), this, SLOT( checkSettingsChanged() ) ); + connect( SourceList::instance()->getLocal()->collection().data(), SIGNAL( tracksAdded( QList ) ), this, SLOT( tracksAdded( QList ) ), Qt::QueuedConnection ); + connect( SourceList::instance()->getLocal()->collection().data(), SIGNAL( tracksRemoved( QList ) ), this, SLOT( tracksRemoved( QList ) ), 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 { diff --git a/src/libtomahawk/EchonestCatalogSynchronizer.h b/src/libtomahawk/EchonestCatalogSynchronizer.h index 393e3bc86..5eda0ddcd 100644 --- a/src/libtomahawk/EchonestCatalogSynchronizer.h +++ b/src/libtomahawk/EchonestCatalogSynchronizer.h @@ -20,6 +20,8 @@ #define ECHONESTCATALOGSYNCHRONIZER_H #include "dllmacro.h" +#include "query.h" +#include "database/databasecommand_trackattributes.h" #include @@ -51,19 +53,25 @@ signals: private slots: void checkSettingsChanged(); + void tracksAdded( const QList& ); + void tracksRemoved( const QList& ); + // 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; }; diff --git a/src/libtomahawk/collection.cpp b/src/libtomahawk/collection.cpp index aa02a285d..bce7851c0 100644 --- a/src/libtomahawk/collection.cpp +++ b/src/libtomahawk/collection.cpp @@ -259,6 +259,7 @@ Collection::delTracks( const QStringList& files ) i++; } + tDebug() << "Emitting tracks removed:" << tracks.size(); emit tracksRemoved( tracks ); } diff --git a/src/libtomahawk/database/databasecommand.cpp b/src/libtomahawk/database/databasecommand.cpp index 9397ba853..1ee2123df 100644 --- a/src/libtomahawk/database/databasecommand.cpp +++ b/src/libtomahawk/database/databasecommand.cpp @@ -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 ); diff --git a/src/libtomahawk/database/databasecommand_collectionattributes.cpp b/src/libtomahawk/database/databasecommand_collectionattributes.cpp index 9454d5e3d..dd950a871 100644 --- a/src/libtomahawk/database/databasecommand_collectionattributes.cpp +++ b/src/libtomahawk/database/databasecommand_collectionattributes.cpp @@ -24,7 +24,6 @@ DatabaseCommand_CollectionAttributes::DatabaseCommand_CollectionAttributes( Data : DatabaseCommand() , m_type( type ) { - qRegisterMetaType< PairList >("PairList"); } void diff --git a/src/libtomahawk/database/databasecommand_collectionattributes.h b/src/libtomahawk/database/databasecommand_collectionattributes.h index 0de1beeab..b6ccd5093 100644 --- a/src/libtomahawk/database/databasecommand_collectionattributes.h +++ b/src/libtomahawk/database/databasecommand_collectionattributes.h @@ -16,16 +16,14 @@ * along with Tomahawk. If not, see . */ -#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 -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 diff --git a/src/libtomahawk/database/databasecommand_deletefiles.cpp b/src/libtomahawk/database/databasecommand_deletefiles.cpp index afc7362ea..8f7779499 100644 --- a/src/libtomahawk/database/databasecommand_deletefiles.cpp +++ b/src/libtomahawk/database/databasecommand_deletefiles.cpp @@ -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() ) diff --git a/src/libtomahawk/database/databasecommand_setcollectionattributes.cpp b/src/libtomahawk/database/databasecommand_setcollectionattributes.cpp index e021cb5a6..9e930397f 100644 --- a/src/libtomahawk/database/databasecommand_setcollectionattributes.cpp +++ b/src/libtomahawk/database/databasecommand_setcollectionattributes.cpp @@ -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 ); diff --git a/src/libtomahawk/database/databasecommand_setcollectionattributes.h b/src/libtomahawk/database/databasecommand_setcollectionattributes.h index be07a3672..41de403e9 100644 --- a/src/libtomahawk/database/databasecommand_setcollectionattributes.h +++ b/src/libtomahawk/database/databasecommand_setcollectionattributes.h @@ -16,8 +16,8 @@ * along with Tomahawk. If not, see . */ -#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 diff --git a/src/libtomahawk/database/databasecommand_settrackattributes.cpp b/src/libtomahawk/database/databasecommand_settrackattributes.cpp new file mode 100644 index 000000000..173e78689 --- /dev/null +++ b/src/libtomahawk/database/databasecommand_settrackattributes.cpp @@ -0,0 +1,97 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2010-2011, Leo Franchi + * + * 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 . + */ + +#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; + + } +} diff --git a/src/libtomahawk/database/databasecommand_settrackattributes.h b/src/libtomahawk/database/databasecommand_settrackattributes.h new file mode 100644 index 000000000..e05619b74 --- /dev/null +++ b/src/libtomahawk/database/databasecommand_settrackattributes.h @@ -0,0 +1,57 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2010-2011, Leo Franchi + * + * 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 . + */ + +#ifndef DATABASECOMMAND_SETTRACKATTRIBUTES +#define DATABASECOMMAND_SETTRACKATTRIBUTES + +#include "typedefs.h" +#include "databasecommandloggable.h" + +#include + +class DatabaseCommand_SetTrackAttributes : public DatabaseCommandLoggable +{ + Q_OBJECT +public: + enum AttributeType { + EchonestCatalogId = 0, + }; + + // Takes a list of 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 diff --git a/src/libtomahawk/database/databasecommand_trackattributes.cpp b/src/libtomahawk/database/databasecommand_trackattributes.cpp new file mode 100644 index 000000000..48fddaded --- /dev/null +++ b/src/libtomahawk/database/databasecommand_trackattributes.cpp @@ -0,0 +1,71 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2010-2011, Leo Franchi + * + * 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 . + */ + +#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 ); +} diff --git a/src/libtomahawk/database/databasecommand_trackattributes.h b/src/libtomahawk/database/databasecommand_trackattributes.h new file mode 100644 index 000000000..261ce0f79 --- /dev/null +++ b/src/libtomahawk/database/databasecommand_trackattributes.h @@ -0,0 +1,51 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2010-2011, Leo Franchi + * + * 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 . + */ + +#ifndef DATABASECOMMAND_TRACKATTRIBUTES_H +#define DATABASECOMMAND_TRACKATTRIBUTES_H + +#include "typedefs.h" +#include "databasecommand.h" +#include "databasecommand_collectionattributes.h" +#include "databasecommand_settrackattributes.h" +#include + +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 diff --git a/src/libtomahawk/typedefs.h b/src/libtomahawk/typedefs.h index 4ef47641b..b3b98232e 100644 --- a/src/libtomahawk/typedefs.h +++ b/src/libtomahawk/typedefs.h @@ -21,6 +21,7 @@ #include #include +#include //template 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() diff --git a/src/tomahawkapp.cpp b/src/tomahawkapp.cpp index 75b0fe6bc..22f36aeb8 100644 --- a/src/tomahawkapp.cpp +++ b/src/tomahawkapp.cpp @@ -367,6 +367,7 @@ TomahawkApp::registerMetaTypes() qRegisterMetaType< QMap< QString, plentry_ptr > >("QMap< QString, plentry_ptr >"); qRegisterMetaType< QHash< QString, QMap > >("QHash< QString, QMap >"); qRegisterMetaType< QMap< QString, QMap< unsigned int, unsigned int > > >("QMap< QString, QMap< unsigned int, unsigned int > >"); + qRegisterMetaType< PairList >("PairList"); qRegisterMetaType< GeneratorMode>("GeneratorMode"); qRegisterMetaType("Tomahawk::GeneratorMode"); diff --git a/src/tomahawkapp.h b/src/tomahawkapp.h index 0b3a0b1a8..00a7749ed 100644 --- a/src/tomahawkapp.h +++ b/src/tomahawkapp.h @@ -135,7 +135,8 @@ private: QxtHttpSessionManager m_session; }; -Q_DECLARE_METATYPE( QPersistentModelIndex ); +Q_DECLARE_METATYPE( QPersistentModelIndex ) +Q_DECLARE_METATYPE(PairList) #endif // TOMAHAWKAPP_H